Advertisement
Guest User

keymap-no-udev.c

a guest
Jul 16th, 2023
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 13.58 KB | None | 0 0
  1. /*
  2.  * keymap - dump keymap of an evdev device or set a new keymap from a file
  3.  *
  4.  * Based on keyfuzz by Lennart Poettering <mzqrovna@0pointer.net>
  5.  * Adapted for udev-extras by Martin Pitt <martin.pitt@ubuntu.com>
  6.  *
  7.  * Copyright (C) 2006, Lennart Poettering
  8.  * Copyright (C) 2009, Canonical Ltd.
  9.  *
  10.  * keymap is free software; you can redistribute it and/or modify it
  11.  * under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * keymap is distributed in the hope that it will be useful, but
  16.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18.  * General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with keymap; if not, write to the Free Software Foundation,
  22.  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  23.  */
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <stdint.h>
  28. #include <ctype.h>
  29. #include <unistd.h>
  30. #include <errno.h>
  31. #include <limits.h>
  32. #include <fcntl.h>
  33. #include <getopt.h>
  34. #include <sys/ioctl.h>
  35. #include <linux/limits.h>
  36. #include <linux/input.h>
  37. #define MAX_SCANCODES 1024
  38. #define SYSCONFDIR "/etc/"
  39. #define PKGLIBEXECDIR "/lib/"
  40. static int evdev_open(const char *dev)
  41. {
  42.         int fd;
  43.         char fn[PATH_MAX];
  44.         if (strncmp(dev, "/dev", 4) != 0) {
  45.                 snprintf(fn, sizeof(fn), "/dev/%s", dev);
  46.                 dev = fn;
  47.         }
  48.         if ((fd = open(dev, O_RDWR)) < 0) {
  49.                 fprintf(stderr, "error open('%s'): %m\n", dev);
  50.                 return -1;
  51.         }
  52.         return fd;
  53. }
  54. static int evdev_get_keycode(int fd, int scancode, int e)
  55. {
  56.         int codes[2];
  57.         codes[0] = scancode;
  58.         if (ioctl(fd, EVIOCGKEYCODE, codes) < 0) {
  59.                 if (e && errno == EINVAL) {
  60.                         return -2;
  61.                 } else {
  62.                         fprintf(stderr, "EVIOCGKEYCODE: %m\n");
  63.                         return -1;
  64.                 }
  65.         }
  66.         return codes[1];
  67. }
  68. static int evdev_set_keycode(int fd, int scancode, int keycode)
  69. {
  70.         int codes[2];
  71.         codes[0] = scancode;
  72.         codes[1] = keycode;
  73.         if (ioctl(fd, EVIOCSKEYCODE, codes) < 0) {
  74.                 fprintf(stderr, "EVIOCSKEYCODE: %m\n");
  75.                 return -1;
  76.         }
  77.         return 0;
  78. }
  79. static int evdev_driver_version(int fd, char *v, size_t l)
  80. {
  81.         int version;
  82.         if (ioctl(fd, EVIOCGVERSION, &version)) {
  83.                 fprintf(stderr, "EVIOCGVERSION: %m\n");
  84.                 return -1;
  85.         }
  86.         snprintf(v, l, "%i.%i.%i.", version >> 16, (version >> 8) & 0xff, version & 0xff);
  87.         return 0;
  88. }
  89. static int evdev_device_name(int fd, char *n, size_t l)
  90. {
  91.         if (ioctl(fd, EVIOCGNAME(l), n) < 0) {
  92.                 fprintf(stderr, "EVIOCGNAME: %m\n");
  93.                 return -1;
  94.         }
  95.         return 0;
  96. }
  97. /* Return a lower-case string with KEY_ prefix removed */
  98. static const char* format_keyname(const char* key) {
  99.         static char result[101];
  100.         const char* s;
  101.         int len;
  102.         for (s = key+4, len = 0; *s && len < 100; ++len, ++s)
  103.                 result[len] = tolower(*s);
  104.         result[len] = '\0';
  105.         return result;
  106. }
  107. static int dump_table(int fd) {
  108.         char version[256], name[256];
  109.         int scancode, r = -1;
  110.         if (evdev_driver_version(fd, version, sizeof(version)) < 0)
  111.                 goto fail;
  112.         if (evdev_device_name(fd, name, sizeof(name)) < 0)
  113.                 goto fail;
  114.         printf("### evdev %s, driver '%s'\n", version, name);
  115.         r = 0;
  116.         for (scancode = 0; scancode < MAX_SCANCODES; scancode++) {
  117.                 int keycode;
  118.                 if ((keycode = evdev_get_keycode(fd, scancode, 1)) < 0) {
  119.                         if (keycode == -2)
  120.                                 continue;
  121.                         r = -1;
  122.                         break;
  123.                 }
  124.                 printf("0x%03x 0x%03x\n", scancode, keycode);
  125.         }
  126. fail:
  127.         return r;
  128. }
  129. static void set_key(int fd, const char* scancode_str, const char* keyname)
  130. {
  131.         unsigned scancode;
  132.         char *endptr;
  133.         char t[105] = "0";
  134.         const struct key *k;
  135.         scancode = (unsigned) strtol(scancode_str, &endptr, 0);
  136.         if (*endptr != '\0') {
  137.                 fprintf(stderr, "ERROR: Invalid scancode\n");
  138.                 exit(1);
  139.         }
  140.         snprintf(t, sizeof(t), "%s", keyname);
  141.         if (evdev_set_keycode(fd, scancode, atoi(t)) < 0)
  142.                 fprintf(stderr, "setting scancode 0x%2X to key code %i failed\n",
  143.                         scancode, atoi(t));
  144.         else
  145.                 printf("setting scancode 0x%2X to key code %i\n",
  146.                         scancode, atoi(t));
  147. }
  148. static int merge_table(int fd, FILE *f) {
  149.         int r = 0;
  150.         int line = 0;
  151.         while (!feof(f)) {
  152.                 char s[256], *p;
  153.                 int scancode, new_keycode, old_keycode;
  154.                 if (!fgets(s, sizeof(s), f))
  155.                         break;
  156.                 line++;
  157.                 p = s+strspn(s, "\t ");
  158.                 if (*p == '#' || *p == '\n')
  159.                         continue;
  160.                 if (sscanf(p, "%i %i", &scancode, &new_keycode) != 2) {
  161.                         char t[105] = "KEY_UNKNOWN";
  162.                         const struct key *k;
  163.                         if (sscanf(p, "%i %100s", &scancode, t+4) != 2) {
  164.                                 fprintf(stderr, "WARNING: Parse failure at line %i, ignoring.\n", line);
  165.                                 r = -1;
  166.                                 continue;
  167.                         }
  168.                         new_keycode = atoi(t);
  169.                 }
  170.                 if ((old_keycode = evdev_get_keycode(fd, scancode, 0)) < 0) {
  171.                         r = -1;
  172.                         goto fail;
  173.                 }
  174.                 if (evdev_set_keycode(fd, scancode, new_keycode) < 0) {
  175.                         r = -1;
  176.                         goto fail;
  177.                 }
  178.                 if (new_keycode != old_keycode)
  179.                         fprintf(stderr, "Remapped scancode 0x%02x to 0x%02x (prior: 0x%02x)\n",
  180.                                 scancode, new_keycode, old_keycode);
  181.         }
  182. fail:
  183.         fclose(f);
  184.         return r;
  185. }
  186. /* read one event; return 1 if valid */
  187. static int read_event(int fd, struct input_event* ev)
  188. {
  189.         int ret;
  190.         ret = read(fd, ev, sizeof(struct input_event));
  191.         if (ret < 0) {
  192.                 perror("read");
  193.                 return 0;
  194.         }
  195.         if (ret != sizeof(struct input_event)) {
  196.                 fprintf(stderr, "did not get enough data for event struct, aborting\n");
  197.                 return 0;
  198.         }
  199.         return 1;
  200. }
  201. static void print_key(uint32_t scancode, uint16_t keycode, int has_scan, int has_key)
  202. {
  203.         const char *keyname = NULL;
  204.         /* ignore key release events */
  205.         if (has_key == 1)
  206.                 return;
  207.         if (has_key == 0 && has_scan != 0) {
  208.                 fprintf(stderr, "got scan code event 0x%02X without a key code event\n",
  209.                         scancode);
  210.                 return;
  211.         }
  212.         if (has_scan != 0)
  213.                 printf("scan code: 0x%02X   ", scancode);
  214.         else
  215.                 printf("(no scan code received)  ");
  216. //        keyname = key_names[keycode];
  217.         if (keyname != NULL)
  218.                 printf("key code: %s\n", format_keyname(keyname));
  219.         else
  220.                 printf("key code: %03X\n", keycode);
  221. }
  222. static void interactive(int fd)
  223. {
  224.         struct input_event ev;
  225.         uint32_t last_scan = 0;
  226.         uint16_t last_key = 0;
  227.         int has_scan; /* boolean */
  228.         int has_key; /* 0: none, 1: release, 2: press */
  229.         /* grab input device */
  230.         ioctl(fd, EVIOCGRAB, 1);
  231.         puts("Press ESC to finish, or Control-C if this device is not your primary keyboard");
  232.         has_scan = has_key = 0;
  233.         while (read_event(fd, &ev)) {
  234.                 /* Drivers usually send the scan code first, then the key code,
  235.                  * then a SYN. Some drivers (like thinkpad_acpi) send the key
  236.                  * code first, and some drivers might not send SYN events, so
  237.                  * keep a robust state machine which can deal with any of those
  238.                  */
  239.                 if (ev.type == EV_MSC && ev.code == MSC_SCAN) {
  240.                         if (has_scan) {
  241.                                 fputs("driver did not send SYN event in between key events; previous event:\n",
  242.                                       stderr);
  243.                                 print_key(last_scan, last_key, has_scan, has_key);
  244.                                 has_key = 0;
  245.                         }
  246.                         last_scan = ev.value;
  247.                         has_scan = 1;
  248.                         /*printf("--- got scan %u; has scan %i key %i\n", last_scan, has_scan, has_key); */
  249.                 }
  250.                 else if (ev.type == EV_KEY) {
  251.                         if (has_key) {
  252.                                 fputs("driver did not send SYN event in between key events; previous event:\n",
  253.                                       stderr);
  254.                                 print_key(last_scan, last_key, has_scan, has_key);
  255.                                 has_scan = 0;
  256.                         }
  257.                         last_key = ev.code;
  258.                         has_key = 1 + ev.value;
  259.                         /*printf("--- got key %hu; has scan %i key %i\n", last_key, has_scan, has_key);*/
  260.                         /* Stop on ESC */
  261.                         if (ev.code == KEY_ESC && ev.value == 0)
  262.                                 break;
  263.                 }
  264.                 else if (ev.type == EV_SYN) {
  265.                         /*printf("--- got SYN; has scan %i key %i\n", has_scan, has_key);*/
  266.                         print_key(last_scan, last_key, has_scan, has_key);
  267.                         has_scan = has_key = 0;
  268.                 }
  269.         }
  270.         /* release input device */
  271.         ioctl(fd, EVIOCGRAB, 0);
  272. }
  273. static void help(int error)
  274. {
  275.         const char* h = "Usage: keymap <event device> [<map file>]\n"
  276.                         "       keymap <event device> scancode keyname [...]\n"
  277.                         "       keymap -i <event device>\n";
  278.         if (error) {
  279.                 fputs(h, stderr);
  280.                 exit(2);
  281.         } else {
  282.                 fputs(h, stdout);
  283.                 exit(0);
  284.         }
  285. }
  286. int main(int argc, char **argv)
  287. {
  288.         static const struct option options[] = {
  289.                 { "help", no_argument, NULL, 'h' },
  290.                 { "interactive", no_argument, NULL, 'i' },
  291.                 {}
  292.         };
  293.         int fd = -1;
  294.         int opt_interactive = 0;
  295.         int i;
  296.         while (1) {
  297.                 int option;
  298.                 option = getopt_long(argc, argv, "hi", options, NULL);
  299.                 if (option == -1)
  300.                         break;
  301.                 switch (option) {
  302.                 case 'h':
  303.                         help(0);
  304.                 case 'i':
  305.                         opt_interactive = 1;
  306.                         break;
  307.                 default:
  308.                         return 1;
  309.                 }
  310.         }
  311.         if (argc < optind+1)
  312.                 help (1);
  313.         if ((fd = evdev_open(argv[optind])) < 0)
  314.                 return 3;
  315.         /* one argument (device): dump or interactive */
  316.         if (argc == optind+1) {
  317.                 if (opt_interactive)
  318.                         interactive(fd);
  319.                 else
  320.                         dump_table(fd);
  321.                 return 0;
  322.         }
  323.         /* two arguments (device, mapfile): set map file */
  324.         if (argc == optind+2) {
  325.                 const char *filearg = argv[optind+1];
  326.                 if (strchr(filearg, '/')) {
  327.                         /* Keymap file argument is a path */
  328.                         FILE *f = fopen(filearg, "r");
  329.                         if (f)
  330.                                 merge_table(fd, f);
  331.                         else
  332.                                 perror(filearg);
  333.                 } else {
  334.                         /* Keymap file argument is a filename */
  335.                         /* Open override file if present, otherwise default file */
  336.                         char keymap_path[PATH_MAX];
  337.                         snprintf(keymap_path, sizeof(keymap_path), "%s%s", SYSCONFDIR "/udev/keymaps/", filearg);
  338.                         FILE *f = fopen(keymap_path, "r");
  339.                         if (f) {
  340.                                 merge_table(fd, f);
  341.                         } else {
  342.                                 snprintf(keymap_path, sizeof(keymap_path), "%s%s", PKGLIBEXECDIR "/keymaps/", filearg);
  343.                                 f = fopen(keymap_path, "r");
  344.                                 if (f)
  345.                                         merge_table(fd, f);
  346.                                 else
  347.                                         perror(keymap_path);
  348.                         }
  349.                 }
  350.                 return 0;
  351.         }
  352.         /* more arguments (device, scancode/keyname pairs): set keys directly */
  353.         if ((argc - optind - 1) % 2 == 0) {
  354.                 for (i = optind+1; i < argc; i += 2)
  355.                         set_key(fd, argv[i], argv[i+1]);
  356.                 return 0;
  357.         }
  358.         /* invalid number of arguments */
  359.         help(1);
  360.         return 1; /* not reached */
  361. }
  362.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement