2 * keymap - dump keymap of an evdev device or set a new keymap from a file
4 * Based on keyfuzz by Lennart Poettering <mzqrovna@0pointer.net>
5 * Adapted for udev-extras by Martin Pitt <martin.pitt@ubuntu.com>
7 * Copyright (C) 2006, Lennart Poettering
8 * Copyright (C) 2009, Canonical Ltd.
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.
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.
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.
35 #include <sys/ioctl.h>
36 #include <linux/limits.h>
37 #include <linux/input.h>
39 const struct key* lookup_key (const char *str, unsigned int len);
41 #include "keys-from-name.h"
42 #include "keys-to-name.h"
46 #define MAX_SCANCODES 1024
48 static int evdev_open(const char *dev)
53 if (!startswith(dev, "/dev")) {
54 snprintf(fn, sizeof(fn), "/dev/%s", dev);
58 if ((fd = open(dev, O_RDWR)) < 0) {
59 fprintf(stderr, "error open('%s'): %m\n", dev);
65 static int evdev_get_keycode(int fd, int scancode, int e)
70 if (ioctl(fd, EVIOCGKEYCODE, codes) < 0) {
71 if (e && errno == EINVAL) {
74 fprintf(stderr, "EVIOCGKEYCODE: %m\n");
81 static int evdev_set_keycode(int fd, int scancode, int keycode)
88 if (ioctl(fd, EVIOCSKEYCODE, codes) < 0) {
89 fprintf(stderr, "EVIOCSKEYCODE: %m\n");
95 static int evdev_driver_version(int fd, char *v, size_t l)
99 if (ioctl(fd, EVIOCGVERSION, &version)) {
100 fprintf(stderr, "EVIOCGVERSION: %m\n");
104 snprintf(v, l, "%i.%i.%i.", version >> 16, (version >> 8) & 0xff, version & 0xff);
108 static int evdev_device_name(int fd, char *n, size_t l)
110 if (ioctl(fd, EVIOCGNAME(l), n) < 0) {
111 fprintf(stderr, "EVIOCGNAME: %m\n");
117 /* Return a lower-case string with KEY_ prefix removed */
118 static const char* format_keyname(const char* key) {
119 static char result[101];
123 for (s = key+4, len = 0; *s && len < 100; ++len, ++s)
124 result[len] = tolower(*s);
129 static int dump_table(int fd) {
130 char version[256], name[256];
131 int scancode, r = -1;
133 if (evdev_driver_version(fd, version, sizeof(version)) < 0)
136 if (evdev_device_name(fd, name, sizeof(name)) < 0)
139 printf("### evdev %s, driver '%s'\n", version, name);
142 for (scancode = 0; scancode < MAX_SCANCODES; scancode++) {
145 if ((keycode = evdev_get_keycode(fd, scancode, 1)) < 0) {
152 if (keycode < KEY_MAX && key_names[keycode])
153 printf("0x%03x %s\n", scancode, format_keyname(key_names[keycode]));
155 printf("0x%03x 0x%03x\n", scancode, keycode);
161 static void set_key(int fd, const char* scancode_str, const char* keyname)
165 char t[105] = "KEY_UNKNOWN";
168 scancode = (unsigned) strtol(scancode_str, &endptr, 0);
169 if (*endptr != '\0') {
170 fprintf(stderr, "ERROR: Invalid scancode\n");
174 snprintf(t, sizeof(t), "KEY_%s", keyname);
176 if (!(k = lookup_key(t, strlen(t)))) {
177 fprintf(stderr, "ERROR: Unknown key name '%s'\n", keyname);
181 if (evdev_set_keycode(fd, scancode, k->id) < 0)
182 fprintf(stderr, "setting scancode 0x%2X to key code %i failed\n",
185 printf("setting scancode 0x%2X to key code %i\n",
189 static int merge_table(int fd, FILE *f) {
195 int scancode, new_keycode, old_keycode;
197 if (!fgets(s, sizeof(s), f))
201 p = s+strspn(s, "\t ");
202 if (*p == '#' || *p == '\n')
205 if (sscanf(p, "%i %i", &scancode, &new_keycode) != 2) {
206 char t[105] = "KEY_UNKNOWN";
209 if (sscanf(p, "%i %100s", &scancode, t+4) != 2) {
210 fprintf(stderr, "WARNING: Parse failure at line %i, ignoring.\n", line);
215 if (!(k = lookup_key(t, strlen(t)))) {
216 fprintf(stderr, "WARNING: Unknown key '%s' at line %i, ignoring.\n", t, line);
225 if ((old_keycode = evdev_get_keycode(fd, scancode, 0)) < 0) {
230 if (evdev_set_keycode(fd, scancode, new_keycode) < 0) {
235 if (new_keycode != old_keycode)
236 fprintf(stderr, "Remapped scancode 0x%02x to 0x%02x (prior: 0x%02x)\n",
237 scancode, new_keycode, old_keycode);
245 /* read one event; return 1 if valid */
246 static int read_event(int fd, struct input_event* ev)
249 ret = read(fd, ev, sizeof(struct input_event));
255 if (ret != sizeof(struct input_event)) {
256 fprintf(stderr, "did not get enough data for event struct, aborting\n");
263 static void print_key(uint32_t scancode, uint16_t keycode, int has_scan, int has_key)
267 /* ignore key release events */
271 if (has_key == 0 && has_scan != 0) {
272 fprintf(stderr, "got scan code event 0x%02X without a key code event\n",
278 printf("scan code: 0x%02X ", scancode);
280 printf("(no scan code received) ");
282 keyname = key_names[keycode];
284 printf("key code: %s\n", format_keyname(keyname));
286 printf("key code: %03X\n", keycode);
289 static void interactive(int fd)
291 struct input_event ev;
292 uint32_t last_scan = 0;
293 uint16_t last_key = 0;
294 int has_scan; /* boolean */
295 int has_key; /* 0: none, 1: release, 2: press */
297 /* grab input device */
298 ioctl(fd, EVIOCGRAB, 1);
299 puts("Press ESC to finish, or Control-C if this device is not your primary keyboard");
301 has_scan = has_key = 0;
302 while (read_event(fd, &ev)) {
303 /* Drivers usually send the scan code first, then the key code,
304 * then a SYN. Some drivers (like thinkpad_acpi) send the key
305 * code first, and some drivers might not send SYN events, so
306 * keep a robust state machine which can deal with any of those
309 if (ev.type == EV_MSC && ev.code == MSC_SCAN) {
311 fputs("driver did not send SYN event in between key events; previous event:\n",
313 print_key(last_scan, last_key, has_scan, has_key);
317 last_scan = ev.value;
319 /*printf("--- got scan %u; has scan %i key %i\n", last_scan, has_scan, has_key); */
321 else if (ev.type == EV_KEY) {
323 fputs("driver did not send SYN event in between key events; previous event:\n",
325 print_key(last_scan, last_key, has_scan, has_key);
330 has_key = 1 + ev.value;
331 /*printf("--- got key %hu; has scan %i key %i\n", last_key, has_scan, has_key);*/
334 if (ev.code == KEY_ESC && ev.value == 0)
337 else if (ev.type == EV_SYN) {
338 /*printf("--- got SYN; has scan %i key %i\n", has_scan, has_key);*/
339 print_key(last_scan, last_key, has_scan, has_key);
341 has_scan = has_key = 0;
346 /* release input device */
347 ioctl(fd, EVIOCGRAB, 0);
350 _noreturn_ static void help(int error)
352 const char* h = "Usage: keymap <event device> [<map file>]\n"
353 " keymap <event device> scancode keyname [...]\n"
354 " keymap -i <event device>\n";
364 int main(int argc, char **argv)
366 static const struct option options[] = {
367 { "help", no_argument, NULL, 'h' },
368 { "interactive", no_argument, NULL, 'i' },
372 int opt_interactive = 0;
378 option = getopt_long(argc, argv, "hi", options, NULL);
397 if ((fd = evdev_open(argv[optind])) < 0)
400 /* one argument (device): dump or interactive */
401 if (argc == optind+1) {
409 /* two arguments (device, mapfile): set map file */
410 if (argc == optind+2) {
411 const char *filearg = argv[optind+1];
412 if (strchr(filearg, '/')) {
413 /* Keymap file argument is a path */
414 FILE *f = fopen(filearg, "re");
420 /* Keymap file argument is a filename */
421 /* Open override file if present, otherwise default file */
422 char keymap_path[PATH_MAX];
424 snprintf(keymap_path, sizeof(keymap_path), "%s%s", SYSCONFDIR "/udev/keymaps/", filearg);
425 f = fopen(keymap_path, "re");
429 snprintf(keymap_path, sizeof(keymap_path), "%s%s", UDEVLIBEXECDIR "/keymaps/", filearg);
430 f = fopen(keymap_path, "re");
440 /* more arguments (device, scancode/keyname pairs): set keys directly */
441 if ((argc - optind - 1) % 2 == 0) {
442 for (i = optind+1; i < argc; i += 2)
443 set_key(fd, argv[i], argv[i+1]);
447 /* invalid number of arguments */
449 return 1; /* not reached */