diff options
Diffstat (limited to 'src/extras/keymap/keymap.c')
-rw-r--r-- | src/extras/keymap/keymap.c | 670 |
1 files changed, 335 insertions, 335 deletions
diff --git a/src/extras/keymap/keymap.c b/src/extras/keymap/keymap.c index 6bcfaefa18..92ec67b3a6 100644 --- a/src/extras/keymap/keymap.c +++ b/src/extras/keymap/keymap.c @@ -45,403 +45,403 @@ const struct key* lookup_key (const char *str, unsigned int len); static int evdev_open(const char *dev) { - int fd; - char fn[PATH_MAX]; - - if (strncmp(dev, "/dev", 4) != 0) { - snprintf(fn, sizeof(fn), "/dev/%s", dev); - dev = fn; - } - - if ((fd = open(dev, O_RDWR)) < 0) { - fprintf(stderr, "error open('%s'): %m\n", dev); - return -1; - } - return fd; + int fd; + char fn[PATH_MAX]; + + if (strncmp(dev, "/dev", 4) != 0) { + snprintf(fn, sizeof(fn), "/dev/%s", dev); + dev = fn; + } + + if ((fd = open(dev, O_RDWR)) < 0) { + fprintf(stderr, "error open('%s'): %m\n", dev); + return -1; + } + return fd; } static int evdev_get_keycode(int fd, int scancode, int e) { - int codes[2]; - - codes[0] = scancode; - if (ioctl(fd, EVIOCGKEYCODE, codes) < 0) { - if (e && errno == EINVAL) { - return -2; - } else { - fprintf(stderr, "EVIOCGKEYCODE: %m\n"); - return -1; - } - } - return codes[1]; + int codes[2]; + + codes[0] = scancode; + if (ioctl(fd, EVIOCGKEYCODE, codes) < 0) { + if (e && errno == EINVAL) { + return -2; + } else { + fprintf(stderr, "EVIOCGKEYCODE: %m\n"); + return -1; + } + } + return codes[1]; } static int evdev_set_keycode(int fd, int scancode, int keycode) { - int codes[2]; + int codes[2]; - codes[0] = scancode; - codes[1] = keycode; + codes[0] = scancode; + codes[1] = keycode; - if (ioctl(fd, EVIOCSKEYCODE, codes) < 0) { - fprintf(stderr, "EVIOCSKEYCODE: %m\n"); - return -1; - } - return 0; + if (ioctl(fd, EVIOCSKEYCODE, codes) < 0) { + fprintf(stderr, "EVIOCSKEYCODE: %m\n"); + return -1; + } + return 0; } static int evdev_driver_version(int fd, char *v, size_t l) { - int version; + int version; - if (ioctl(fd, EVIOCGVERSION, &version)) { - fprintf(stderr, "EVIOCGVERSION: %m\n"); - return -1; - } + if (ioctl(fd, EVIOCGVERSION, &version)) { + fprintf(stderr, "EVIOCGVERSION: %m\n"); + return -1; + } - snprintf(v, l, "%i.%i.%i.", version >> 16, (version >> 8) & 0xff, version & 0xff); - return 0; + snprintf(v, l, "%i.%i.%i.", version >> 16, (version >> 8) & 0xff, version & 0xff); + return 0; } static int evdev_device_name(int fd, char *n, size_t l) { - if (ioctl(fd, EVIOCGNAME(l), n) < 0) { - fprintf(stderr, "EVIOCGNAME: %m\n"); - return -1; - } - return 0; + if (ioctl(fd, EVIOCGNAME(l), n) < 0) { + fprintf(stderr, "EVIOCGNAME: %m\n"); + return -1; + } + return 0; } /* Return a lower-case string with KEY_ prefix removed */ static const char* format_keyname(const char* key) { - static char result[101]; - const char* s; - int len; - - for (s = key+4, len = 0; *s && len < 100; ++len, ++s) - result[len] = tolower(*s); - result[len] = '\0'; - return result; + static char result[101]; + const char* s; + int len; + + for (s = key+4, len = 0; *s && len < 100; ++len, ++s) + result[len] = tolower(*s); + result[len] = '\0'; + return result; } static int dump_table(int fd) { - char version[256], name[256]; - int scancode, r = -1; + char version[256], name[256]; + int scancode, r = -1; - if (evdev_driver_version(fd, version, sizeof(version)) < 0) - goto fail; + if (evdev_driver_version(fd, version, sizeof(version)) < 0) + goto fail; - if (evdev_device_name(fd, name, sizeof(name)) < 0) - goto fail; + if (evdev_device_name(fd, name, sizeof(name)) < 0) + goto fail; - printf("### evdev %s, driver '%s'\n", version, name); + printf("### evdev %s, driver '%s'\n", version, name); - r = 0; - for (scancode = 0; scancode < MAX_SCANCODES; scancode++) { - int keycode; + r = 0; + for (scancode = 0; scancode < MAX_SCANCODES; scancode++) { + int keycode; - if ((keycode = evdev_get_keycode(fd, scancode, 1)) < 0) { - if (keycode == -2) - continue; - r = -1; - break; - } + if ((keycode = evdev_get_keycode(fd, scancode, 1)) < 0) { + if (keycode == -2) + continue; + r = -1; + break; + } - if (keycode < KEY_MAX && key_names[keycode]) - printf("0x%03x %s\n", scancode, format_keyname(key_names[keycode])); - else - printf("0x%03x 0x%03x\n", scancode, keycode); - } + if (keycode < KEY_MAX && key_names[keycode]) + printf("0x%03x %s\n", scancode, format_keyname(key_names[keycode])); + else + printf("0x%03x 0x%03x\n", scancode, keycode); + } fail: - return r; + return r; } static void set_key(int fd, const char* scancode_str, const char* keyname) { - unsigned scancode; - char *endptr; - char t[105] = "KEY_UNKNOWN"; - const struct key *k; - - scancode = (unsigned) strtol(scancode_str, &endptr, 0); - if (*endptr != '\0') { - fprintf(stderr, "ERROR: Invalid scancode\n"); - exit(1); - } - - snprintf(t, sizeof(t), "KEY_%s", keyname); - - if (!(k = lookup_key(t, strlen(t)))) { - fprintf(stderr, "ERROR: Unknown key name '%s'\n", keyname); - exit(1); - } - - if (evdev_set_keycode(fd, scancode, k->id) < 0) - fprintf(stderr, "setting scancode 0x%2X to key code %i failed\n", - scancode, k->id); - else - printf("setting scancode 0x%2X to key code %i\n", - scancode, k->id); + unsigned scancode; + char *endptr; + char t[105] = "KEY_UNKNOWN"; + const struct key *k; + + scancode = (unsigned) strtol(scancode_str, &endptr, 0); + if (*endptr != '\0') { + fprintf(stderr, "ERROR: Invalid scancode\n"); + exit(1); + } + + snprintf(t, sizeof(t), "KEY_%s", keyname); + + if (!(k = lookup_key(t, strlen(t)))) { + fprintf(stderr, "ERROR: Unknown key name '%s'\n", keyname); + exit(1); + } + + if (evdev_set_keycode(fd, scancode, k->id) < 0) + fprintf(stderr, "setting scancode 0x%2X to key code %i failed\n", + scancode, k->id); + else + printf("setting scancode 0x%2X to key code %i\n", + scancode, k->id); } static int merge_table(int fd, FILE *f) { - int r = 0; - int line = 0; - - while (!feof(f)) { - char s[256], *p; - int scancode, new_keycode, old_keycode; - - if (!fgets(s, sizeof(s), f)) - break; - - line++; - p = s+strspn(s, "\t "); - if (*p == '#' || *p == '\n') - continue; - - if (sscanf(p, "%i %i", &scancode, &new_keycode) != 2) { - char t[105] = "KEY_UNKNOWN"; - const struct key *k; - - if (sscanf(p, "%i %100s", &scancode, t+4) != 2) { - fprintf(stderr, "WARNING: Parse failure at line %i, ignoring.\n", line); - r = -1; - continue; - } - - if (!(k = lookup_key(t, strlen(t)))) { - fprintf(stderr, "WARNING: Unknown key '%s' at line %i, ignoring.\n", t, line); - r = -1; - continue; - } - - new_keycode = k->id; - } - - - if ((old_keycode = evdev_get_keycode(fd, scancode, 0)) < 0) { - r = -1; - goto fail; - } - - if (evdev_set_keycode(fd, scancode, new_keycode) < 0) { - r = -1; - goto fail; - } - - if (new_keycode != old_keycode) - fprintf(stderr, "Remapped scancode 0x%02x to 0x%02x (prior: 0x%02x)\n", - scancode, new_keycode, old_keycode); - } + int r = 0; + int line = 0; + + while (!feof(f)) { + char s[256], *p; + int scancode, new_keycode, old_keycode; + + if (!fgets(s, sizeof(s), f)) + break; + + line++; + p = s+strspn(s, "\t "); + if (*p == '#' || *p == '\n') + continue; + + if (sscanf(p, "%i %i", &scancode, &new_keycode) != 2) { + char t[105] = "KEY_UNKNOWN"; + const struct key *k; + + if (sscanf(p, "%i %100s", &scancode, t+4) != 2) { + fprintf(stderr, "WARNING: Parse failure at line %i, ignoring.\n", line); + r = -1; + continue; + } + + if (!(k = lookup_key(t, strlen(t)))) { + fprintf(stderr, "WARNING: Unknown key '%s' at line %i, ignoring.\n", t, line); + r = -1; + continue; + } + + new_keycode = k->id; + } + + + if ((old_keycode = evdev_get_keycode(fd, scancode, 0)) < 0) { + r = -1; + goto fail; + } + + if (evdev_set_keycode(fd, scancode, new_keycode) < 0) { + r = -1; + goto fail; + } + + if (new_keycode != old_keycode) + fprintf(stderr, "Remapped scancode 0x%02x to 0x%02x (prior: 0x%02x)\n", + scancode, new_keycode, old_keycode); + } fail: - fclose(f); - return r; + fclose(f); + return r; } /* read one event; return 1 if valid */ static int read_event(int fd, struct input_event* ev) { - int ret; - ret = read(fd, ev, sizeof(struct input_event)); - - if (ret < 0) { - perror("read"); - return 0; - } - if (ret != sizeof(struct input_event)) { - fprintf(stderr, "did not get enough data for event struct, aborting\n"); - return 0; - } - - return 1; + int ret; + ret = read(fd, ev, sizeof(struct input_event)); + + if (ret < 0) { + perror("read"); + return 0; + } + if (ret != sizeof(struct input_event)) { + fprintf(stderr, "did not get enough data for event struct, aborting\n"); + return 0; + } + + return 1; } static void print_key(uint32_t scancode, uint16_t keycode, int has_scan, int has_key) { - const char *keyname; - - /* ignore key release events */ - if (has_key == 1) - return; - - if (has_key == 0 && has_scan != 0) { - fprintf(stderr, "got scan code event 0x%02X without a key code event\n", - scancode); - return; - } - - if (has_scan != 0) - printf("scan code: 0x%02X ", scancode); - else - printf("(no scan code received) "); - - keyname = key_names[keycode]; - if (keyname != NULL) - printf("key code: %s\n", format_keyname(keyname)); - else - printf("key code: %03X\n", keycode); + const char *keyname; + + /* ignore key release events */ + if (has_key == 1) + return; + + if (has_key == 0 && has_scan != 0) { + fprintf(stderr, "got scan code event 0x%02X without a key code event\n", + scancode); + return; + } + + if (has_scan != 0) + printf("scan code: 0x%02X ", scancode); + else + printf("(no scan code received) "); + + keyname = key_names[keycode]; + if (keyname != NULL) + printf("key code: %s\n", format_keyname(keyname)); + else + printf("key code: %03X\n", keycode); } static void interactive(int fd) { - struct input_event ev; - uint32_t last_scan = 0; - uint16_t last_key = 0; - int has_scan; /* boolean */ - int has_key; /* 0: none, 1: release, 2: press */ - - /* grab input device */ - ioctl(fd, EVIOCGRAB, 1); - puts("Press ESC to finish, or Control-C if this device is not your primary keyboard"); - - has_scan = has_key = 0; - while (read_event(fd, &ev)) { - /* Drivers usually send the scan code first, then the key code, - * then a SYN. Some drivers (like thinkpad_acpi) send the key - * code first, and some drivers might not send SYN events, so - * keep a robust state machine which can deal with any of those - */ - - if (ev.type == EV_MSC && ev.code == MSC_SCAN) { - if (has_scan) { - fputs("driver did not send SYN event in between key events; previous event:\n", - stderr); - print_key(last_scan, last_key, has_scan, has_key); - has_key = 0; - } - - last_scan = ev.value; - has_scan = 1; - /*printf("--- got scan %u; has scan %i key %i\n", last_scan, has_scan, has_key); */ - } - else if (ev.type == EV_KEY) { - if (has_key) { - fputs("driver did not send SYN event in between key events; previous event:\n", - stderr); - print_key(last_scan, last_key, has_scan, has_key); - has_scan = 0; - } - - last_key = ev.code; - has_key = 1 + ev.value; - /*printf("--- got key %hu; has scan %i key %i\n", last_key, has_scan, has_key);*/ - - /* Stop on ESC */ - if (ev.code == KEY_ESC && ev.value == 0) - break; - } - else if (ev.type == EV_SYN) { - /*printf("--- got SYN; has scan %i key %i\n", has_scan, has_key);*/ - print_key(last_scan, last_key, has_scan, has_key); - - has_scan = has_key = 0; - } - - } - - /* release input device */ - ioctl(fd, EVIOCGRAB, 0); + struct input_event ev; + uint32_t last_scan = 0; + uint16_t last_key = 0; + int has_scan; /* boolean */ + int has_key; /* 0: none, 1: release, 2: press */ + + /* grab input device */ + ioctl(fd, EVIOCGRAB, 1); + puts("Press ESC to finish, or Control-C if this device is not your primary keyboard"); + + has_scan = has_key = 0; + while (read_event(fd, &ev)) { + /* Drivers usually send the scan code first, then the key code, + * then a SYN. Some drivers (like thinkpad_acpi) send the key + * code first, and some drivers might not send SYN events, so + * keep a robust state machine which can deal with any of those + */ + + if (ev.type == EV_MSC && ev.code == MSC_SCAN) { + if (has_scan) { + fputs("driver did not send SYN event in between key events; previous event:\n", + stderr); + print_key(last_scan, last_key, has_scan, has_key); + has_key = 0; + } + + last_scan = ev.value; + has_scan = 1; + /*printf("--- got scan %u; has scan %i key %i\n", last_scan, has_scan, has_key); */ + } + else if (ev.type == EV_KEY) { + if (has_key) { + fputs("driver did not send SYN event in between key events; previous event:\n", + stderr); + print_key(last_scan, last_key, has_scan, has_key); + has_scan = 0; + } + + last_key = ev.code; + has_key = 1 + ev.value; + /*printf("--- got key %hu; has scan %i key %i\n", last_key, has_scan, has_key);*/ + + /* Stop on ESC */ + if (ev.code == KEY_ESC && ev.value == 0) + break; + } + else if (ev.type == EV_SYN) { + /*printf("--- got SYN; has scan %i key %i\n", has_scan, has_key);*/ + print_key(last_scan, last_key, has_scan, has_key); + + has_scan = has_key = 0; + } + + } + + /* release input device */ + ioctl(fd, EVIOCGRAB, 0); } static void help(int error) { - const char* h = "Usage: keymap <event device> [<map file>]\n" - " keymap <event device> scancode keyname [...]\n" - " keymap -i <event device>\n"; - if (error) { - fputs(h, stderr); - exit(2); - } else { - fputs(h, stdout); - exit(0); - } + const char* h = "Usage: keymap <event device> [<map file>]\n" + " keymap <event device> scancode keyname [...]\n" + " keymap -i <event device>\n"; + if (error) { + fputs(h, stderr); + exit(2); + } else { + fputs(h, stdout); + exit(0); + } } int main(int argc, char **argv) { - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "interactive", no_argument, NULL, 'i' }, - {} - }; - int fd = -1; - int opt_interactive = 0; - int i; - - while (1) { - int option; - - option = getopt_long(argc, argv, "hi", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'h': - help(0); - - case 'i': - opt_interactive = 1; - break; - default: - return 1; - } - } - - if (argc < optind+1) - help (1); - - if ((fd = evdev_open(argv[optind])) < 0) - return 3; - - /* one argument (device): dump or interactive */ - if (argc == optind+1) { - if (opt_interactive) - interactive(fd); - else - dump_table(fd); - return 0; - } - - /* two arguments (device, mapfile): set map file */ - if (argc == optind+2) { - const char *filearg = argv[optind+1]; - if (strchr(filearg, '/')) { - /* Keymap file argument is a path */ - FILE *f = fopen(filearg, "r"); - if (f) - merge_table(fd, f); - else - perror(filearg); - } else { - /* Keymap file argument is a filename */ - /* Open override file if present, otherwise default file */ - char keymap_path[PATH_MAX]; - snprintf(keymap_path, sizeof(keymap_path), "%s%s", SYSCONFDIR "/udev/keymaps/", filearg); - FILE *f = fopen(keymap_path, "r"); - if (f) { - merge_table(fd, f); - } else { - snprintf(keymap_path, sizeof(keymap_path), "%s%s", PKGLIBEXECDIR "/keymaps/", filearg); - f = fopen(keymap_path, "r"); - if (f) - merge_table(fd, f); - else - perror(keymap_path); - } - } - return 0; - } - - /* more arguments (device, scancode/keyname pairs): set keys directly */ - if ((argc - optind - 1) % 2 == 0) { - for (i = optind+1; i < argc; i += 2) - set_key(fd, argv[i], argv[i+1]); - return 0; - } - - /* invalid number of arguments */ - help(1); - return 1; /* not reached */ + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "interactive", no_argument, NULL, 'i' }, + {} + }; + int fd = -1; + int opt_interactive = 0; + int i; + + while (1) { + int option; + + option = getopt_long(argc, argv, "hi", options, NULL); + if (option == -1) + break; + + switch (option) { + case 'h': + help(0); + + case 'i': + opt_interactive = 1; + break; + default: + return 1; + } + } + + if (argc < optind+1) + help (1); + + if ((fd = evdev_open(argv[optind])) < 0) + return 3; + + /* one argument (device): dump or interactive */ + if (argc == optind+1) { + if (opt_interactive) + interactive(fd); + else + dump_table(fd); + return 0; + } + + /* two arguments (device, mapfile): set map file */ + if (argc == optind+2) { + const char *filearg = argv[optind+1]; + if (strchr(filearg, '/')) { + /* Keymap file argument is a path */ + FILE *f = fopen(filearg, "r"); + if (f) + merge_table(fd, f); + else + perror(filearg); + } else { + /* Keymap file argument is a filename */ + /* Open override file if present, otherwise default file */ + char keymap_path[PATH_MAX]; + snprintf(keymap_path, sizeof(keymap_path), "%s%s", SYSCONFDIR "/udev/keymaps/", filearg); + FILE *f = fopen(keymap_path, "r"); + if (f) { + merge_table(fd, f); + } else { + snprintf(keymap_path, sizeof(keymap_path), "%s%s", PKGLIBEXECDIR "/keymaps/", filearg); + f = fopen(keymap_path, "r"); + if (f) + merge_table(fd, f); + else + perror(keymap_path); + } + } + return 0; + } + + /* more arguments (device, scancode/keyname pairs): set keys directly */ + if ((argc - optind - 1) % 2 == 0) { + for (i = optind+1; i < argc; i += 2) + set_key(fd, argv[i], argv[i+1]); + return 0; + } + + /* invalid number of arguments */ + help(1); + return 1; /* not reached */ } |