improve license notice
[evhz] / evhz.c
1 /* The license of this program follows the GNU license recommendations at */
2 /* https://www.gnu.org/licenses/license-recommendations.en.html. They */
3 /* recommend that small programs, < 300 lines, be licensed under the */
4 /* Apache License 2.0. This file contains or is part of one or more small */
5 /* programs. */
6
7 /* Copyright (C) 2016 Ian Kelling */
8
9 /* Licensed under the Apache License, Version 2.0 (the "License"); */
10 /* you may not use this file except in compliance with the License. */
11 /* You may obtain a copy of the License at */
12
13 /* http://www.apache.org/licenses/LICENSE-2.0 */
14
15 /* Unless required by applicable law or agreed to in writing, software */
16 /* distributed under the License is distributed on an "AS IS" BASIS, */
17 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
18 /* See the License for the specific language governing permissions and */
19 /* limitations under the License. */
20 #include <string.h>
21 #include <stdio.h>
22 #include <linux/input.h>
23 #include <fcntl.h>
24 #include <signal.h>
25 #include <getopt.h>
26 #include <unistd.h>
27
28 #define EVENTS 400
29 #define HZ_LIST 64
30
31 typedef struct event_s {
32 int fd;
33 int hz[HZ_LIST];
34 int count;
35 int avghz;
36 unsigned long long prev_time;
37 char name[128];
38 } event_t;
39
40 int quit = 0;
41
42 void sigint() {
43 quit = 1;
44 }
45
46 int main(int argc, char *argv[]) {
47 int optch;
48 int i;
49 event_t events[EVENTS];
50 int verbose = 1;
51 int max_event = 0;
52
53 while((optch = getopt(argc, argv, "hn")) != -1) {
54 switch(optch) {
55 case('h'):
56 printf("Usage: %s [-n|-h]\n", argv[0]);
57 printf("-n nonverbose\n");
58 printf("-h help\n");
59 return 0;
60 break;
61 case('n'):
62 verbose = 0;
63 break;
64 }
65 }
66
67 if(geteuid() != 0) {
68 printf("%s must be used as superuser\n", argv[0]);
69 return 1;
70 }
71
72 signal(SIGINT, sigint);
73
74 printf("Press CTRL-C to exit.\n\n");
75
76 memset(events, 0, sizeof(events));
77
78 // List input devices
79 for(i = 0; i < EVENTS; i++) {
80 // 20 is needed for 3 digits of event devs under the expected format, but
81 // just give it some extra in case.
82 char device[30];
83
84 sprintf(device, "/dev/input/event%i", i);
85 events[i].fd = open(device, O_RDONLY);
86
87 if(events[i].fd != -1) {
88 max_event = i;
89 ioctl(events[i].fd, EVIOCGNAME(sizeof(events[i].name)), events[i].name);
90 if(verbose) printf("event%i: %s\n", i, events[i].name);
91 }
92 }
93
94 while(!quit) {
95 fd_set set;
96
97 FD_ZERO(&set);
98
99 for(i = 0; i <= max_event; i++) {
100 if(events[i].fd != -1) {
101 FD_SET(events[i].fd, &set);
102 }
103 }
104
105 if(select(FD_SETSIZE, &set, NULL, NULL, NULL) <= 0) {
106 continue;
107 }
108
109 int bytes;
110 struct input_event event;
111
112 for(i = 0; i <= max_event; i++) {
113 if(events[i].fd == -1 || !FD_ISSET(events[i].fd, &set)) {
114 continue;
115 }
116
117 bytes = read(events[i].fd, &event, sizeof(event));
118
119 if(bytes != sizeof(event)) {
120 continue;
121 }
122
123 if(event.type == EV_REL || event.type == EV_ABS) {
124 unsigned long long time, timediff;
125 unsigned hz = 0;
126
127 time = (unsigned long long)event.time.tv_sec * 1000000ULL;
128 time += (unsigned long long)event.time.tv_usec;
129
130 timediff = time - events[i].prev_time;
131
132 if(timediff != 0)
133 hz = 1000000ULL / timediff;
134
135 if(hz > 0) {
136 unsigned j, maxavg;
137
138 events[i].count++;
139 events[i].hz[events[i].count & (HZ_LIST - 1)] = hz;
140
141 events[i].avghz = 0;
142
143 maxavg = (events[i].count > HZ_LIST) ? HZ_LIST : events[i].count;
144
145 for(j = 0; j < maxavg; j++) {
146 events[i].avghz += events[i].hz[j];
147 }
148
149 events[i].avghz /= maxavg;
150
151 if(verbose) printf("%s: Latest % 5iHz, Average % 5iHz\n", events[i].name, hz, events[i].avghz);
152 }
153
154 events[i].prev_time = time;
155 }
156 }
157 }
158
159 for(i = 0; i < max_event; i++) {
160 if(events[i].fd != -1) {
161 if (events[i].avghz != 0) {
162 printf("\nAverage for %s: % 5iHz\n", events[i].name, events[i].avghz);
163 }
164 close(events[i].fd);
165 }
166 }
167
168 return 0;
169 }