/* * $Id: evtest.c,v 1.18 2002/07/17 08:50:55 vojtech Exp $ * * Copyright (c) 1999-2000 Vojtech Pavlik * * Event device test program */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include #include #include #include #include #include #include char *events[EV_MAX + 2] = { "SYN", "KEY", "REL", "ABS", "MSC", "SW", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "LED", "SND", NULL, "REP", "FF", "PWR", "FF_STATUS", NULL }; char *keys[KEY_MAX + 2] = { "RESERVED", "ESC", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "MINUS", "EQUAL", "BACKSPACE", "TAB", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "LEFTBRACE", "RIGHTBRACE", "ENTER", "LEFTCTRL", "A", "S", "D", "F", "G", "H", "J", "K", "L", "SEMICOLON", "APOSTROPHE", "GRAVE", "LEFTSHIFT", "BACKSLASH", "Z", "X", "C", "V", "B", "N", "M", "COMMA", "DOT", "SLASH", "RIGHTSHIFT", "KPASTERISK", "LEFTALT", "SPACE", "CAPSLOCK", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "NUMLOCK", "SCROLLLOCK", "KP7", "KP8", "KP9", "KPMINUS", "KP4", "KP5", "KP6", "KPPLUS", "KP1", "KP2", "KP3", "KP0", "KPDOT", NULL, "ZENKAKUHANKAKU", "102ND", "F11", "F12", "RO", "KATAKANA", "HIRAGANA", "HENKAN", "KATAKANAHIRAGANA", "MUHENKAN", "KPJPCOMMA", "KPENTER", "RIGHTCTRL", "KPSLASH", "SYSRQ", "RIGHTALT", "LINEFEED", "HOME", "UP", "PAGEUP", "LEFT", "RIGHT", "END", "DOWN", "PAGEDOWN", "INSERT", "DELETE", "MACRO", "MUTE", "VOLUMEDOWN", "VOLUMEUP", "POWER", "KPEQUAL", "KPPLUSMINUS", "PAUSE", NULL, "KPCOMMA", "HANGEUL", "HANJA", "YEN", "LEFTMETA", "RIGHTMETA", "COMPOSE", "STOP", "AGAIN", "PROPS", "UNDO", "FRONT", "COPY", "OPEN", "PASTE", "FIND", "CUT", "HELP", "MENU", "CALC", "SETUP", "SLEEP", "WAKEUP", "FILE", "SENDFILE", "DELETEFILE", "XFER", "PROG1", "PROG2", "WWW", "MSDOS", "COFFEE", "DIRECTION", "CYCLEWINDOWS", "MAIL", "BOOKMARKS", "COMPUTER", "BACK", "FORWARD", "CLOSECD", "EJECTCD", "EJECTCLOSECD", "NEXTSONG", "PLAYPAUSE", "PREVIOUSSONG", "STOPCD", "RECORD", "REWIND", "PHONE", "ISO", "CONFIG", "HOMEPAGE", "REFRESH", "EXIT", "MOVE", "EDIT", "SCROLLUP", "SCROLLDOWN", "KPLEFTPAREN", "KPRIGHTPAREN", "NEW", "REDO", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", NULL, NULL, NULL, NULL, NULL, "PLAYCD", "PAUSECD", "PROG3", "PROG4", NULL, "SUSPEND", "CLOSE", "PLAY", "FASTFORWARD", "BASSBOOST", "PRINT", "HP", "CAMERA", "SOUND", "QUESTION", "EMAIL", "CHAT", "SEARCH", "CONNECT", "FINANCE", "SPORT", "SHOP", "ALTERASE", "CANCEL", "BRIGHTNESSDOWN", "BRIGHTNESSUP", "MEDIA", "SWITCHVIDEOMODE", "KBDILLUMTOGGLE", "KBDILLUMDOWN", "KBDILLUMUP", "SEND", "REPLY", "FORWARDMAIL", "SAVE", "DOCUMENTS", "BATTERY", NULL, NULL, NULL, "UNKNOWN", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "OK", "SELECT", "GOTO", "CLEAR", "POWER2", "OPTION", "INFO", "TIME", "VENDOR", "ARCHIVE", "PROGRAM", "CHANNEL", "FAVORITES", "EPG", "PVR", "MHP", "LANGUAGE", "TITLE", "SUBTITLE", "ANGLE", "ZOOM", "MODE", "KEYBOARD", "SCREEN", "PC", "TV", "TV2", "VCR", "VCR2", "SAT", "SAT2", "CD", "TAPE", "RADIO", "TUNER", "PLAYER", "TEXT", "DVD", "AUX", "MP3", "AUDIO", "VIDEO", "DIRECTORY", "LIST", "MEMO", "CALENDAR", "RED", "GREEN", "YELLOW", "BLUE", "CHANNELUP", "CHANNELDOWN", "FIRST", "LAST", "AB", "NEXT", "RESTART", "SLOW", "SHUFFLE", "BREAK", "PREVIOUS", "DIGITS", "TEEN", "TWEN", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "DEL_EOL", "DEL_EOS", "INS_LINE", "DEL_LINE", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "FN", "FN_ESC", "FN_F1", "FN_F2", "FN_F3", "FN_F4", "FN_F5", "FN_F6", "FN_F7", "FN_F8", "FN_F9", "FN_F10", "FN_F11", "FN_F12", "FN_1", "FN_2", "FN_D", "FN_E", "FN_F", "FN_S", "FN_B", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "BRL_DOT1", "BRL_DOT2", "BRL_DOT3", "BRL_DOT4", "BRL_DOT5", "BRL_DOT6", "BRL_DOT7", "BRL_DOT8", NULL }; char *relatives[REL_MAX + 2] = { "X", "Y", "Z", "RX", "RY", "RZ", "HWHEEL", "DIAL", "WHEEL", "MISC", NULL }; char *absolutes[ABS_MAX + 2] = { "X", "Y", "Z", "RX", "RY", "RZ", "THROTTLE", "RUDDER", "WHEEL", "GAS", "BRAKE", NULL, NULL, NULL, NULL, NULL, "HAT0X", "HAT0Y", "HAT1X", "HAT1Y", "HAT2X", "HAT2Y", "HAT3X", "HAT3Y", "PRESSURE", "DISTANCE", "TILT_X", "TILT_Y", "TOOL_WIDTH", NULL, NULL, NULL, "VOLUME", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "MISC", NULL }; char *leds[LED_MAX + 2] = { "NUML", "CAPSL", "SCROLLL", "COMPOSE", "KANA", "SLEEP", "SUSPEND", "MUTE", "MISC", "MAIL", "CHARGING", NULL }; char *repeats[REP_MAX + 2] = { "DELAY", "PERIOD", NULL }; char *sounds[SND_MAX + 2] = { "CLICK", "BELL", "TONE", NULL }; char *miscs[MSC_MAX + 2] = { "SERIAL", "PULSELED", "GESTURE", "RAW", "SCAN", NULL }; char *absval[5] = { "Value", "Min ", "Max ", "Fuzz ", "Flat " }; char **names[EV_MAX + 1] = { events, keys, relatives, absolutes, miscs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, leds, sounds, NULL, repeats, NULL, NULL, NULL }; #define BITS_PER_LONG (sizeof(long) * 8) #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) #define OFF(x) ((x)%BITS_PER_LONG) #define LONG(x) ((x)/BITS_PER_LONG) #define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1) #define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */ #define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */ #define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) /* get unique identifier */ #define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */ int main (int argc, char **argv) { int fd, rd, i, j, k; struct input_event ev[64]; int version, grab; unsigned short id[4]; unsigned long bit[EV_MAX][NBITS(KEY_MAX)]; char name[256] = "Unknown"; char phys[256] = "Unknown"; char uniq[256] = "Unknown"; int abs[5]; int x, y, oldx, oldy, dX, dY; if (argc < 3) { printf("Usage: evtest /dev/input/eventX \n"); printf("Where X = input device number\n"); printf("and = 1 to grab the dev, and 0 not to.\n"); exit(1); } if ((fd = open(argv[1], O_RDONLY)) < 0) { perror("evtest"); exit(1); } grab = strtol(argv[2], NULL, 0); if (ioctl(fd, EVIOCGVERSION, &version)) { perror("evtest: can't get version"); exit(1); } printf("Input driver version is %d.%d.%d\n", version >> 16, (version >> 8) & 0xff, version & 0xff); ioctl(fd, EVIOCGID, id); printf("Input device ID: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n", id[ID_BUS], id[ID_VENDOR], id[ID_PRODUCT], id[ID_VERSION]); if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) >= 0) printf("Input device name: \"%s\"\n", name); else printf("No name.\n"); if (ioctl(fd, EVIOCGUNIQ(sizeof(uniq)), uniq) >= 0) printf("Input device uniq: \"%s\"\n", uniq); else printf("No uniq.\n"); if (ioctl(fd, EVIOCGPHYS(sizeof(phys)), phys) >= 0) printf("Input device phys: \"%s\"\n", phys); else printf("No phys.\n"); memset(bit, 0, sizeof(bit)); ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]); printf("Supported events:\n"); for (i = 0; i < EV_MAX; i++) if (test_bit(i, bit[0])) { printf(" Event type %d (%s)\n", i, events[i] ? events[i] : "?"); ioctl(fd, EVIOCGBIT(i, KEY_MAX), bit[i]); for (j = 0; j < KEY_MAX; j++) if (test_bit(j, bit[i])) { printf(" Event code %d (%s)\n", j, names[i] ? (names[i][j] ? names[i][j] : "?") : "?"); if (i == EV_ABS) { ioctl(fd, EVIOCGABS(j), abs); for (k = 0; k < 5; k++) if ((k < 3) || abs[k]) printf(" %s %6d\n", absval[k], abs[k]); } } } printf("Grabbing: "); rd = ioctl(fd, EVIOCGRAB, grab); printf("%d -%d-%s-\n", grab, rd, strerror(errno)); fflush(stdout); printf("Testing ... (interrupt to exit)\n"); while (1) { rd = read(fd, ev, sizeof(struct input_event) * 64); if (rd < (int) sizeof(struct input_event)) { printf("yyy\n"); perror("\nevtest: error reading"); exit (1); } for (i = 0; i < rd / sizeof(struct input_event); i++) printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n", ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].type, events[ev[i].type] ? events[ev[i].type] : "?", ev[i].code, names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?", ev[i].value); } }