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.
34 #include <sys/ioctl.h>
35 #include <linux/input.h>
37 const struct key* lookup_key (const char *str, unsigned int len);
39 #include "keys-from-name.h"
40 #include "keys-to-name.h"
42 #define MAX_SCANCODES 1024
44 /* If keymap file is given without a path, assume this one; must end with '/' * */
45 #define DEFAULT_PATH "/lib/udev/keymaps/"
47 static int evdev_open(const char *dev)
52 if (strncmp(dev, "/dev", 4) != 0) {
53 snprintf(fn, sizeof(fn), "/dev/%s", dev);
57 if ((fd = open(dev, O_RDWR)) < 0) {
58 fprintf(stderr, "error open('%s'): %m\n", dev);
64 static int evdev_get_keycode(int fd, int scancode, int e)
69 if (ioctl(fd, EVIOCGKEYCODE, codes) < 0) {
70 if (e && errno == EINVAL) {
73 fprintf(stderr, "EVIOCGKEYCODE: %m\n");
80 static int evdev_set_keycode(int fd, int scancode, int keycode)
87 if (ioctl(fd, EVIOCSKEYCODE, codes) < 0) {
88 fprintf(stderr, "EVIOCSKEYCODE: %m\n");
94 static int evdev_driver_version(int fd, char *v, size_t l)
98 if (ioctl(fd, EVIOCGVERSION, &version)) {
99 fprintf(stderr, "EVIOCGVERSION: %m\n");
103 snprintf(v, l, "%i.%i.%i.", version >> 16, (version >> 8) & 0xff, version & 0xff);
107 static int evdev_device_name(int fd, char *n, size_t l)
109 if (ioctl(fd, EVIOCGNAME(l), n) < 0) {
110 fprintf(stderr, "EVIOCGNAME: %m\n");
116 /* Return a lower-case string with KEY_ prefix removed */
117 static const char* format_keyname(const char* key) {
118 static char result[101];
122 for (s = key+4, len = 0; *s && len < 100; ++len, ++s)
123 result[len] = tolower(*s);
128 static int dump_table(int fd) {
129 char version[256], name[256];
130 int scancode, r = -1;
132 if (evdev_driver_version(fd, version, sizeof(version)) < 0)
135 if (evdev_device_name(fd, name, sizeof(name)) < 0)
138 printf("### evdev %s, driver '%s'\n", version, name);
141 for (scancode = 0; scancode < MAX_SCANCODES; scancode++) {
144 if ((keycode = evdev_get_keycode(fd, scancode, 1)) < 0) {
150 if (keycode < KEY_MAX && key_names[keycode])
151 printf("0x%03x %s\n", scancode, format_keyname(key_names[keycode]));
153 printf("0x%03x 0x%03x\n", scancode, keycode);
159 static int merge_table(int fd, const char *filename) {
164 f = fopen(filename, "r");
173 int scancode, new_keycode, old_keycode;
175 if (!fgets(s, sizeof(s), f))
179 p = s+strspn(s, "\t ");
180 if (*p == '#' || *p == '\n')
183 if (sscanf(p, "%i %i", &scancode, &new_keycode) != 2) {
184 char t[105] = "KEY_UNKNOWN";
187 if (sscanf(p, "%i %100s", &scancode, t+4) != 2) {
188 fprintf(stderr, "WARNING: Parse failure at line %i, ignoring.\n", line);
193 if (!(k = lookup_key(t, strlen(t)))) {
194 fprintf(stderr, "WARNING: Unknown key '%s' at line %i, ignoring.\n", t, line);
203 if ((old_keycode = evdev_get_keycode(fd, scancode, 0)) < 0) {
208 if (evdev_set_keycode(fd, scancode, new_keycode) < 0) {
213 if (new_keycode != old_keycode)
214 fprintf(stderr, "Remapped scancode 0x%02x to 0x%02x (prior: 0x%02x)\n",
215 scancode, new_keycode, old_keycode);
221 static const char* default_keymap_path(const char* path)
223 static char result[PATH_MAX];
225 if (!strchr(path, '/')) {
226 snprintf(result, sizeof(result), "%s%s", DEFAULT_PATH, path);
232 static void print_key(struct input_event *event)
234 static int cur_scancode = 0;
236 /* save scan code for next EV_KEY event */
237 if (event->type == EV_MSC && event->code == MSC_SCAN)
238 cur_scancode = event->value;
241 if (event->type == EV_KEY && event->value)
242 printf("scan code: 0x%02X key code: %s\n", cur_scancode,
243 format_keyname(key_names[event->code]));
246 static void interactive(int fd)
248 struct input_event ev;
251 /* grab input device */
252 ioctl(fd, EVIOCGRAB, 1);
254 puts("Press ESC to finish");
256 switch (read(fd, &ev, sizeof(ev))) {
266 /* stop on Escape key release */
267 if (ev.type == EV_KEY && ev.code == KEY_ESC && ev.value == 0)
273 /* release input device */
274 ioctl(fd, EVIOCGRAB, 0);
277 int main(int argc, char **argv)
279 static const struct option options[] = {
280 { "help", no_argument, NULL, 'h' },
281 { "interactive", no_argument, NULL, 'i' },
285 int opt_interactive = 0;
290 option = getopt_long(argc, argv, "hi", options, NULL);
296 printf("Usage: keymap <event device> [<map file>]\n\n");
307 if (argc < optind+1 || argc > optind+2) {
308 fprintf(stderr, "Usage: keymap <event device> [<map file>]\n\n");
312 if ((fd = evdev_open(argv[optind])) < 0)
315 if (argc == optind+2)
316 merge_table(fd, default_keymap_path(argv[optind+1]));