improve license notice
[evhz] / evhz.c
diff --git a/evhz.c b/evhz.c
index a34fd83277723d9397905669bc8a47451ef10a1b..950f727fcc6a7cd379fc76e153420878bfed6208 100644 (file)
--- a/evhz.c
+++ b/evhz.c
@@ -1,3 +1,22 @@
+/* The license of this program  follows the GNU license recommendations at */
+/* https://www.gnu.org/licenses/license-recommendations.en.html. They */
+/* recommend that small programs, < 300 lines, be licensed under the */
+/* Apache License 2.0. This file contains or is part of one or more small */
+/* programs. */
+
+/* Copyright (C) 2016 Ian Kelling */
+
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+
+/*     http://www.apache.org/licenses/LICENSE-2.0 */
+
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
+/* See the License for the specific language governing permissions and */
+/* limitations under the License. */
 #include <string.h>
 #include <stdio.h>
 #include <linux/input.h>
 #include <getopt.h>
 #include <unistd.h>
 
-#define EVENTS 50
+#define EVENTS 400
 #define HZ_LIST 64
 
 typedef struct event_s {
-       int fd;
-       int hz[HZ_LIST];
-       int count;
-       int avghz;
-       double prvtime;
-       char name[128];
+    int fd;
+    int hz[HZ_LIST];
+    int count;
+    int avghz;
+    unsigned long long prev_time;
+    char name[128];
 } event_t;
 
 int quit = 0;
 
 void sigint() {
-       quit = 1;
+    quit = 1;
 }
 
 int main(int argc, char *argv[]) {
-       int optch;
-       int i;
-       event_t events[EVENTS];
-       int verbose = 0;
-
-       while((optch = getopt(argc, argv, "hv")) != -1) {
-               switch(optch) {
-                       case('h'):
-                               printf("Usage: %s [-v|-h]\n", argv[0]);
-                               return 0;
-                               break;
-                       case('v'):
-                               verbose = 1;
-                               break;
-               }
-       }
-
-       signal(SIGINT, sigint);
-
-       printf("Press CTRL-C to exit.\n\n");
-
-       memset(events, 0, sizeof(events));
-
-       // List input devices
-       for(i = 0; i < EVENTS; i++) {
-               char device[18];
-
-               sprintf(device, "/dev/input/event%i", i);
-               events[i].fd = open(device, O_RDONLY);
+    int optch;
+    int i;
+    event_t events[EVENTS];
+    int verbose = 1;
+    int max_event = 0;
+
+    while((optch = getopt(argc, argv, "hn")) != -1) {
+        switch(optch) {
+        case('h'):
+            printf("Usage: %s [-n|-h]\n", argv[0]);
+            printf("-n     nonverbose\n");
+            printf("-h     help\n");
+            return 0;
+            break;
+        case('n'):
+            verbose = 0;
+            break;
+        }
+    }
+
+    if(geteuid() != 0) {
+        printf("%s must be used as superuser\n", argv[0]);
+        return 1;
+    }
+
+    signal(SIGINT, sigint);
+
+    printf("Press CTRL-C to exit.\n\n");
+
+    memset(events, 0, sizeof(events));
+
+    // List input devices
+    for(i = 0; i < EVENTS; i++) {
+        // 20 is needed for 3 digits of event devs under the expected format, but
+        // just give it some extra in case.
+        char device[30];
+
+        sprintf(device, "/dev/input/event%i", i);
+        events[i].fd = open(device, O_RDONLY);
                
-               if(events[i].fd != -1) {
-                       ioctl(events[i].fd, EVIOCGNAME(sizeof(events[i].name)), events[i].name);
-                       if(verbose) printf("event%i: %s\n", i, events[i].name);
-               }
-       }
+        if(events[i].fd != -1) {
+            max_event = i;
+            ioctl(events[i].fd, EVIOCGNAME(sizeof(events[i].name)), events[i].name);
+            if(verbose) printf("event%i: %s\n", i, events[i].name);
+        }
+    }
+
+    while(!quit) {
+        fd_set set;
+
+        FD_ZERO(&set);
+
+        for(i = 0; i <= max_event; i++) {
+            if(events[i].fd != -1) {
+                FD_SET(events[i].fd, &set);
+            }
+        }
+
+        if(select(FD_SETSIZE, &set, NULL, NULL, NULL) <= 0) {
+            continue;
+        }
 
-       while(!quit) {
-               fd_set set;
+        int bytes;
+        struct input_event event;
 
-               FD_ZERO(&set);
+        for(i = 0; i <= max_event; i++) {
+            if(events[i].fd == -1 || !FD_ISSET(events[i].fd, &set)) {
+                continue;
+            }
 
-               for(i = 0; i < EVENTS; i++) {
-                       if(events[i].fd != -1) {
-                               FD_SET(events[i].fd, &set);
-                       }
-               }
+            bytes = read(events[i].fd, &event, sizeof(event));
 
-               if(select(FD_SETSIZE, &set, NULL, NULL, NULL) > 0) {
-                       int bytes;
-                       struct input_event event;
+            if(bytes != sizeof(event)) {
+                continue;
+            }
 
-                       for(i = 0; i < EVENTS; i++) {
-                               if(events[i].fd == -1 || !FD_ISSET(events[i].fd, &set)) {
-                                       continue;
-                               }
+            if(event.type == EV_REL || event.type == EV_ABS) {
+                unsigned long long time, timediff;
+                unsigned hz = 0;
 
-                               bytes = read(events[i].fd, &event, sizeof(event));
+                time = (unsigned long long)event.time.tv_sec * 1000000ULL;
+                time += (unsigned long long)event.time.tv_usec;
 
-                               if(bytes != sizeof(event)) {
-                                       continue;
-                               }
+                timediff = time - events[i].prev_time;
 
-                               if(event.type == EV_REL) {
-                                       double time;
-                                       int hz;
+                if(timediff != 0)
+                    hz = 1000000ULL / timediff;
 
-                                       time = event.time.tv_sec * 1000 + event.time.tv_usec / 1000;
-                                       hz = 1000 / (time - events[i].prvtime);
+                if(hz > 0) {
+                    unsigned j, maxavg;
 
-                                       if(hz > 0) {
-                                               int j;
+                    events[i].count++;
+                    events[i].hz[events[i].count & (HZ_LIST - 1)] = hz;
 
-                                               events[i].count++;
-                                               events[i].hz[events[i].count & (HZ_LIST - 1)] = hz;
+                    events[i].avghz = 0;
 
-                                               events[i].avghz = 0;
+                    maxavg = (events[i].count > HZ_LIST) ? HZ_LIST : events[i].count;
 
-                                               for(j = 0; j < HZ_LIST; j++) {
-                                                       events[i].avghz += events[i].hz[j];
-                                               }
+                    for(j = 0; j < maxavg; j++) {
+                        events[i].avghz += events[i].hz[j];
+                    }
 
-                                               events[i].avghz /= (events[i].count > HZ_LIST) ? HZ_LIST : events[i].count;
+                    events[i].avghz /= maxavg;
 
-                                               if(verbose) printf("%s: Latest % 5iHz, Average % 5iHz\n", events[i].name, hz, events[i].avghz);
-                                       }
+                    if(verbose) printf("%s: Latest % 5iHz, Average % 5iHz\n", events[i].name, hz, events[i].avghz);
+                }
 
-                                       events[i].prvtime = time;
-                               }
-                       }
-               }
-       }
+                events[i].prev_time = time;
+            }
+        }
+    }
 
-       for(i = 0; i < EVENTS; i++) {
-               if(events[i].fd != -1) {
-                       if (events[i].avghz != 0) {
-                               printf("\nAverage for %s: % 5iHz\n", events[i].name, events[i].avghz);
-                       }
-                       close(events[i].fd);
-               }
-       }
+    for(i = 0; i < max_event; i++) {
+        if(events[i].fd != -1) {
+            if (events[i].avghz != 0) {
+                printf("\nAverage for %s: % 5iHz\n", events[i].name, events[i].avghz);
+            }
+            close(events[i].fd);
+        }
+    }
 
-       return 0;
+    return 0;
 }