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 pressedX
movement in x-direction-1 -> left
and1 -> right
Y
movement in y-direction-1 -> down
and1 -> 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);
}
}