Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Linux input

Some notes on using /dev/input/* device driver files.

mouseX / mice

These device files are created by the mousedev driver.

  • /dev/input/mouseX represents the input stream for a SINGLE mouse device.
  • /dev/input/mice represents the merged input stream for ALL mouse devices.

The data stream consists of 3 bytes per event. An event is encoded as (BTN, X, Y).

  • BTN button pressed
  • X movement in x-direction -1 -> left and 1 -> right
  • Y movement in y-direction -1 -> down and 1 -> up

The raw data stream can be inspected as follows.

sudo cat /dev/input/mice | od -tx1 -w3 -v

eventX

These device files are created by the evdev driver.

  • /dev/input/eventX represents the generic input event interface a SINGLE input device.

Input events are encoded as given by the input_event struct below. Reading from the eventX device file will always yield whole number of input events.

struct input_event { struct timeval time; unsigned short type; unsigned short code; unsigned int value; };

On most 64bit machines the raw data stream can be inspected as follows.

sudo cat /dev/input/event4 | od -tx1 -w24 -v

Identifying device files.

To find out which device file is assigned to which input device the following file /proc/bus/input/devices in the proc filesystem can be consulted.

This yields entries as follows and shows which Handlers are assigned to which Name.

I: Bus=0018 Vendor=04f3 Product=0033 Version=0000 N: Name="Elan Touchpad" ... H: Handlers=event15 mouse0 ...

Example: Toying with /dev/input/eventX

Once compiled, the example should be run as sudo ./event /dev/input/eventX.

#include <stdio.h> #include <fcntl.h> #include <assert.h> #include <unistd.h> #include <time.h> #include <sys/time.h> #include <linux/input-event-codes.h> struct input_event { struct timeval time; unsigned short type; unsigned short code; unsigned int value; }; const char* type(unsigned short t) { static char buf[32]; const char* fmt = "0x%x"; switch (t) { #define FMT(TYPE) case TYPE: fmt = #TYPE"(0x%x)"; break FMT(EV_SYN); FMT(EV_KEY); FMT(EV_REL); FMT(EV_ABS); #undef FMT } snprintf(buf, sizeof(buf), fmt, t); return buf; } const char* code(unsigned short c) { static char buf[32]; const char* fmt = "0x%x"; switch (c) { #define FMT(CODE) case CODE: fmt = #CODE"(0x%x)"; break FMT(BTN_LEFT); FMT(BTN_RIGHT); FMT(BTN_MIDDLE); FMT(REL_X); FMT(REL_Y); #undef FMT } snprintf(buf, sizeof(buf), fmt, c); return buf; } const char* timefmt(const struct timeval* t) { assert(t); struct tm* lt = localtime(&t->tv_sec); // Returns pointer to static tm object. static char buf[64]; strftime(buf, sizeof(buf), "%H:%M:%S", lt); return buf; } int main(int argc, char* argv[]) { assert(argc == 2); int fd = open(argv[1], O_RDONLY); assert(fd != -1); struct input_event inp; while (1) { int ret = read(fd, &inp, sizeof(inp)); assert(ret == sizeof(inp)); printf("time: %s type: %s code: %s value: 0x%x\n", timefmt(&inp.time), type(inp.type), code(inp.code), inp.value); } }