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