~iank/evhz

1c5e7224be5b0a3a3040f2e8392bc30f9e3a310b — Ian Kelling 8 years ago 5f6cab7
general improvements
3 files changed, 47 insertions(+), 37 deletions(-)

M README.md
M evhz.c
A run
M README.md => README.md +3 -4
@@ 4,12 4,11 @@ Display the current mouse refresh rate under linux with evdev

For information about polling rate, see https://wiki.archlinux.org/index.php/Mouse_Polling_Rate

The program is just evhz.c. Compile and run:
Just do ./run (run is very short and readable).

    gcc -o evhz evhz.c
    sudo ./evhz
Nonverbose mode = -n, but you probably don't want that.

Nonverbose mode = -n
Reported average is for the last 64 samples, or as many as we have so far.

There exists a kernel bug for USB ports which use the uhci_hcd driver,
where a 1000 hz mouse will only read at 500hz, causing jittering:

M evhz.c => evhz.c +39 -33
@@ 19,7 19,7 @@
#include <getopt.h>
#include <unistd.h>

#define EVENTS 50
#define EVENTS 200
#define HZ_LIST 64

typedef struct event_s {


@@ 27,7 27,7 @@ typedef struct event_s {
    int hz[HZ_LIST];
    int count;
    int avghz;
    double prvtime;
    double prev_time;
    char name[128];
} event_t;



@@ 42,6 42,7 @@ int main(int argc, char *argv[]) {
    int i;
    event_t events[EVENTS];
    int verbose = 1;
    int max_event = 0;

    while((optch = getopt(argc, argv, "hn")) != -1) {
        switch(optch) {


@@ 70,12 71,15 @@ int main(int argc, char *argv[]) {

    // List input devices
    for(i = 0; i < EVENTS; i++) {
        char device[19];
        // 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) {
            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);
        }


@@ 86,58 90,60 @@ int main(int argc, char *argv[]) {

        FD_ZERO(&set);

        for(i = 0; i < EVENTS; i++) {
        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) {
            int bytes;
            struct input_event event;

            for(i = 0; i < EVENTS; i++) {
                if(events[i].fd == -1 || !FD_ISSET(events[i].fd, &set)) {
                    continue;
                }
        if(select(FD_SETSIZE, &set, NULL, NULL, NULL) <= 0) {
            continue;
        }

                bytes = read(events[i].fd, &event, sizeof(event));
        int bytes;
        struct input_event event;

                if(bytes != sizeof(event)) {
                    continue;
                }
        for(i = 0; i <= max_event; i++) {
            if(events[i].fd == -1 || !FD_ISSET(events[i].fd, &set)) {
                continue;
            }

                if(event.type == EV_REL || event.type == EV_ABS) {
                    double time;
                    int hz;
            bytes = read(events[i].fd, &event, sizeof(event));

                    time = event.time.tv_sec * 1000 + event.time.tv_usec / 1000;
                    hz = 1000 / (time - events[i].prvtime);
            if(bytes != sizeof(event)) {
                continue;
            }

                    if(hz > 0) {
                        int j;
            if(event.type == EV_REL || event.type == EV_ABS) {
                double time;
                int hz;

                        events[i].count++;
                        events[i].hz[events[i].count & (HZ_LIST - 1)] = hz;
                time = event.time.tv_sec * 1000 + event.time.tv_usec / 1000;
                hz = 1000 / (time - events[i].prev_time);

                        events[i].avghz = 0;
                if(hz > 0) {
                    int j;

                        for(j = 0; j < HZ_LIST; j++) {
                            events[i].avghz += events[i].hz[j];
                        }
                    events[i].count++;
                    events[i].hz[events[i].count & (HZ_LIST - 1)] = hz;

                        events[i].avghz /= (events[i].count > HZ_LIST) ? HZ_LIST : events[i].count;
                    events[i].avghz = 0;

                        if(verbose) printf("%s: Latest % 5iHz, Average % 5iHz\n", events[i].name, hz, events[i].avghz);
                    for(j = 0; j < HZ_LIST; j++) {
                        events[i].avghz += events[i].hz[j];
                    }

                    events[i].prvtime = time;
                    events[i].avghz /= (events[i].count > HZ_LIST) ? HZ_LIST : events[i].count;

                    if(verbose) printf("%s: Latest % 5iHz, Average % 5iHz\n", events[i].name, hz, events[i].avghz);
                }

                events[i].prev_time = time;
            }
        }
    }

    for(i = 0; i < EVENTS; i++) {
    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);

A run => run +5 -0
@@ 0,0 1,5 @@
#!/bin/bash
cd "${BASH_SOURCE%/*}"
gcc -o evhz evhz.c
[[ $EUID == 0 ]] || s=sudo
$s ./evhz "$@"