--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <linux/input.h>
+
+int main(int argc, char **argv)
+{
+ int c, ret, fd;
+ struct input_event iev;
+ int grab, decode;
+
+ if(argc < 2) {
+ fprintf(stderr, "usage: evcat [-gd] FILE\n");
+ exit(1);
+ }
+ grab = decode = 0;
+ while((c = getopt(argc, argv, "gd")) > 0) {
+ switch(c) {
+ case 'g':
+ grab = 1;
+ break;
+ case 'd':
+ decode = 1;
+ break;
+ default:
+ exit(1);
+ }
+ }
+ if((fd = open(argv[optind], O_RDONLY)) < 0) {
+ perror(argv[optind]);
+ exit(1);
+ }
+ if(grab && ioctl(fd, EVIOCGRAB, 1)) {
+ perror("EVIOCGRAB");
+ exit(1);
+ }
+ while(1) {
+ ret = read(fd, &iev, sizeof(iev));
+ if(ret < 0) {
+ perror("read");
+ exit(1);
+ }
+ if(ret == 0)
+ break;
+ if(decode) {
+ printf("%010lu.%06lu:\t", iev.time.tv_sec, iev.time.tv_usec);
+ switch(iev.type) {
+ case EV_SYN:
+ printf("sync\t");
+ switch(iev.code) {
+ case SYN_REPORT:
+ printf("report");
+ break;
+ case SYN_CONFIG:
+ printf("config");
+ break;
+ default:
+ printf("%04x", iev.code);
+ }
+ break;
+ case EV_KEY:
+ printf("key\t%i\t%i", iev.code, iev.value);
+ break;
+ case EV_REL:
+ printf("rel\t");
+ switch(iev.code) {
+ case REL_X:
+ printf("x\t%04i", iev.value);
+ break;
+ case REL_Y:
+ printf("y\t%04i", iev.value);
+ break;
+ case REL_Z:
+ printf("z\t%04i", iev.value);
+ break;
+ case REL_RX:
+ printf("rx\t%04i", iev.value);
+ break;
+ case REL_RY:
+ printf("ry\t%04i", iev.value);
+ break;
+ case REL_RZ:
+ printf("rz\t%04i", iev.value);
+ break;
+ case REL_HWHEEL:
+ printf("hwheel\t%04i", iev.value);
+ break;
+ case REL_DIAL:
+ printf("dial\t%04i", iev.value);
+ break;
+ case REL_WHEEL:
+ printf("wheel\t%04i", iev.value);
+ break;
+ case REL_MISC:
+ printf("misc\t%04i", iev.value);
+ break;
+ }
+ break;
+ case EV_ABS:
+ printf("abs\t");
+ switch(iev.code) {
+ case ABS_X:
+ printf("x\t%04i", iev.value);
+ break;
+ case ABS_Y:
+ printf("y\t%04i", iev.value);
+ break;
+ case ABS_Z:
+ printf("z\t%04i", iev.value);
+ break;
+ case ABS_RX:
+ printf("rx\t%04i", iev.value);
+ break;
+ case ABS_RY:
+ printf("ry\t%04i", iev.value);
+ break;
+ case ABS_RZ:
+ printf("rz\t%04i", iev.value);
+ break;
+ case ABS_THROTTLE:
+ printf("throttle\t%04i", iev.value);
+ break;
+ case ABS_RUDDER:
+ printf("rudder\t%04i", iev.value);
+ break;
+ case ABS_WHEEL:
+ printf("wheel\t%04i", iev.value);
+ break;
+ case ABS_GAS:
+ printf("gas\t%04i", iev.value);
+ break;
+ case ABS_BRAKE:
+ printf("brake\t%04i", iev.value);
+ break;
+ case ABS_PRESSURE:
+ printf("pressure\t%04i", iev.value);
+ break;
+ case ABS_DISTANCE:
+ printf("distance\t%04i", iev.value);
+ break;
+ case ABS_TILT_X:
+ printf("tilt-x\t%04i", iev.value);
+ break;
+ case ABS_TILT_Y:
+ printf("tilt-y\t%04i", iev.value);
+ break;
+ case ABS_TOOL_WIDTH:
+ printf("width\t%04i", iev.value);
+ break;
+ case ABS_VOLUME:
+ printf("volume\t%04i", iev.value);
+ break;
+ case ABS_MISC:
+ printf("misc\t%04i", iev.value);
+ break;
+ }
+ break;
+ case EV_MSC:
+ printf("misc\t");
+ switch(iev.code) {
+ case MSC_SERIAL:
+ printf("serial\t%i", iev.value);
+ break;
+ case MSC_PULSELED:
+ printf("pled\t%i", iev.value);
+ break;
+ case MSC_GESTURE:
+ printf("gesture\t%i", iev.value);
+ break;
+ case MSC_RAW:
+ printf("raw\t%i", iev.value);
+ break;
+ case MSC_SCAN:
+ printf("scan\t%i", iev.value);
+ break;
+ }
+ break;
+ case EV_LED:
+ printf("led\t");
+ switch(iev.code) {
+ case LED_NUML:
+ printf("num\t");
+ break;
+ case LED_CAPSL:
+ printf("caps\t");
+ break;
+ case LED_SCROLLL:
+ printf("scroll\t");
+ break;
+ default:
+ printf("%i\t", iev.code);
+ break;
+ }
+ printf("%i", iev.value);
+ break;
+ case EV_SND:
+ printf("sound\t%i\t%i", iev.code, iev.value);
+ break;
+ case EV_REP:
+ printf("repeat\t");
+ switch(iev.code) {
+ case REP_DELAY:
+ printf("delay\t");
+ break;
+ case REP_PERIOD:
+ printf("period\t");
+ break;
+ default:
+ printf("%i\t", iev.code);
+ break;
+ }
+ printf("%i", iev.value);
+ break;
+ default:
+ printf("%04x %04x %08x", iev.type, iev.code, iev.value);
+ break;
+ }
+ printf("\n");
+ } else {
+ printf("%010lu.%06lu: %04x %04x %08x\n", iev.time.tv_sec, iev.time.tv_usec, iev.type, iev.code, iev.value);
+ }
+ fflush(stdout);
+ }
+ if(grab && ioctl(fd, EVIOCGRAB, 0)) {
+ perror("EVIOC(un)GRAB");
+ exit(1);
+ }
+ close(fd);
+ return(0);
+}