chiark / gitweb /
keymap: Fix scan codes > 0x7FFFFFFF
[elogind.git] / src / udev / keymap / keymap.c
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
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdint.h>
29 #include <ctype.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <limits.h>
33 #include <fcntl.h>
34 #include <getopt.h>
35 #include <sys/ioctl.h>
36 #include <linux/limits.h>
37 #include <linux/input.h>
38
39 const struct key* lookup_key (const char *str, unsigned int len);
40
41 #include "keys-from-name.h"
42 #include "keys-to-name.h"
43 #include "macro.h"
44 #include "util.h"
45
46 #define MAX_SCANCODES 1024
47
48 static int evdev_open(const char *dev)
49 {
50         int fd;
51         char fn[PATH_MAX];
52
53         if (!startswith(dev, "/dev")) {
54                 snprintf(fn, sizeof(fn), "/dev/%s", dev);
55                 dev = fn;
56         }
57
58         if ((fd = open(dev, O_RDWR)) < 0) {
59                 fprintf(stderr, "error open('%s'): %m\n", dev);
60                 return -1;
61         }
62         return fd;
63 }
64
65 static int evdev_get_keycode(int fd, unsigned scancode, int e)
66 {
67         unsigned codes[2];
68
69         codes[0] = scancode;
70         if (ioctl(fd, EVIOCGKEYCODE, codes) < 0) {
71                 if (e && errno == EINVAL) {
72                         return -2;
73                 } else {
74                         fprintf(stderr, "EVIOCGKEYCODE: %m\n");
75                         return -1;
76                 }
77         }
78         return codes[1];
79 }
80
81 static int evdev_set_keycode(int fd, unsigned scancode, int keycode)
82 {
83         unsigned codes[2];
84
85         codes[0] = scancode;
86         codes[1] = (unsigned) keycode;
87
88         if (ioctl(fd, EVIOCSKEYCODE, codes) < 0) {
89                 fprintf(stderr, "EVIOCSKEYCODE: %m\n");
90                 return -1;
91         }
92         return 0;
93 }
94
95 static int evdev_driver_version(int fd, char *v, size_t l)
96 {
97         int version;
98
99         if (ioctl(fd, EVIOCGVERSION, &version)) {
100                 fprintf(stderr, "EVIOCGVERSION: %m\n");
101                 return -1;
102         }
103
104         snprintf(v, l, "%i.%i.%i.", version >> 16, (version >> 8) & 0xff, version & 0xff);
105         return 0;
106 }
107
108 static int evdev_device_name(int fd, char *n, size_t l)
109 {
110         if (ioctl(fd, EVIOCGNAME(l), n) < 0) {
111                 fprintf(stderr, "EVIOCGNAME: %m\n");
112                 return -1;
113         }
114         return 0;
115 }
116
117 /* Return a lower-case string with KEY_ prefix removed */
118 static const char* format_keyname(const char* key) {
119         static char result[101];
120         const char* s;
121         int len;
122
123         for (s = key+4, len = 0; *s && len < 100; ++len, ++s)
124                 result[len] = tolower(*s);
125         result[len] = '\0';
126         return result;
127 }
128
129 static int dump_table(int fd) {
130         char version[256], name[256];
131         unsigned scancode;
132         int r = -1;
133
134         if (evdev_driver_version(fd, version, sizeof(version)) < 0)
135                 goto fail;
136
137         if (evdev_device_name(fd, name, sizeof(name)) < 0)
138                 goto fail;
139
140         printf("### evdev %s, driver '%s'\n", version, name);
141
142         r = 0;
143         for (scancode = 0; scancode < MAX_SCANCODES; scancode++) {
144                 int keycode;
145
146                 if ((keycode = evdev_get_keycode(fd, scancode, 1)) < 0) {
147                         if (keycode == -2)
148                                 continue;
149                         r = -1;
150                         break;
151                 }
152
153                 if (keycode < KEY_MAX && key_names[keycode])
154                         printf("0x%03x %s\n", scancode, format_keyname(key_names[keycode]));
155                 else
156                         printf("0x%03x 0x%03x\n", scancode, keycode);
157         }
158 fail:
159         return r;
160 }
161
162 static void set_key(int fd, const char* scancode_str, const char* keyname)
163 {
164         unsigned scancode;
165         char *endptr;
166         char t[105] = "KEY_UNKNOWN";
167         const struct key *k;
168
169         scancode = (unsigned) strtol(scancode_str, &endptr, 0);
170         if (*endptr != '\0') {
171                 fprintf(stderr, "ERROR: Invalid scancode\n");
172                 exit(1);
173         }
174
175         snprintf(t, sizeof(t), "KEY_%s", keyname);
176
177         if (!(k = lookup_key(t, strlen(t)))) {
178                 fprintf(stderr, "ERROR: Unknown key name '%s'\n", keyname);
179                 exit(1);
180         }
181
182         if (evdev_set_keycode(fd, scancode, k->id) < 0)
183                 fprintf(stderr, "setting scancode 0x%2X to key code %i failed\n",
184                         scancode, k->id);
185         else
186                 printf("setting scancode 0x%2X to key code %i\n",
187                         scancode, k->id);
188 }
189
190 static int merge_table(int fd, FILE *f) {
191         int r = 0;
192         int line = 0;
193
194         while (!feof(f)) {
195                 char s[256], *p;
196                 unsigned scancode;
197                 int new_keycode, old_keycode;
198
199                 if (!fgets(s, sizeof(s), f))
200                         break;
201
202                 line++;
203                 p = s+strspn(s, "\t ");
204                 if (*p == '#' || *p == '\n')
205                         continue;
206
207                 if (sscanf(p, "%u %i", &scancode, &new_keycode) != 2) {
208                         char t[105] = "KEY_UNKNOWN";
209                         const struct key *k;
210
211                         if (sscanf(p, "%u %100s", &scancode, t+4) != 2) {
212                                 fprintf(stderr, "WARNING: Parse failure at line %i, ignoring.\n", line);
213                                 r = -1;
214                                 continue;
215                         }
216
217                         if (!(k = lookup_key(t, strlen(t)))) {
218                                 fprintf(stderr, "WARNING: Unknown key '%s' at line %i, ignoring.\n", t, line);
219                                 r = -1;
220                                 continue;
221                         }
222
223                         new_keycode = k->id;
224                 }
225
226
227                 if ((old_keycode = evdev_get_keycode(fd, scancode, 0)) < 0) {
228                         r = -1;
229                         goto fail;
230                 }
231
232                 if (evdev_set_keycode(fd, scancode, new_keycode) < 0) {
233                         r = -1;
234                         goto fail;
235                 }
236
237                 if (new_keycode != old_keycode)
238                         fprintf(stderr, "Remapped scancode 0x%02x to 0x%02x (prior: 0x%02x)\n",
239                                 scancode, new_keycode, old_keycode);
240         }
241 fail:
242         fclose(f);
243         return r;
244 }
245
246
247 /* read one event; return 1 if valid */
248 static int read_event(int fd, struct input_event* ev)
249 {
250         int ret;
251         ret = read(fd, ev, sizeof(struct input_event));
252
253         if (ret < 0) {
254                 perror("read");
255                 return 0;
256         }
257         if (ret != sizeof(struct input_event)) {
258                 fprintf(stderr, "did not get enough data for event struct, aborting\n");
259                 return 0;
260         }
261
262         return 1;
263 }
264
265 static void print_key(unsigned scancode, uint16_t keycode, int has_scan, int has_key)
266 {
267         const char *keyname;
268
269         /* ignore key release events */
270         if (has_key == 1)
271                 return;
272
273         if (has_key == 0 && has_scan != 0) {
274                 fprintf(stderr, "got scan code event 0x%02X without a key code event\n",
275                         scancode);
276                 return;
277         }
278
279         if (has_scan != 0)
280                 printf("scan code: 0x%02X   ", scancode);
281         else
282                 printf("(no scan code received)  ");
283
284         keyname = key_names[keycode];
285         if (keyname != NULL)
286                 printf("key code: %s\n", format_keyname(keyname));
287         else
288                 printf("key code: %03X\n", keycode);
289 }
290
291 static void interactive(int fd)
292 {
293         struct input_event ev;
294         unsigned last_scan = 0;
295         uint16_t last_key = 0;
296         int has_scan; /* boolean */
297         int has_key; /* 0: none, 1: release, 2: press */
298
299         /* grab input device */
300         ioctl(fd, EVIOCGRAB, 1);
301         puts("Press ESC to finish, or Control-C if this device is not your primary keyboard");
302
303         has_scan = has_key = 0;
304         while (read_event(fd, &ev)) {
305                 /* Drivers usually send the scan code first, then the key code,
306                  * then a SYN. Some drivers (like thinkpad_acpi) send the key
307                  * code first, and some drivers might not send SYN events, so
308                  * keep a robust state machine which can deal with any of those
309                  */
310
311                 if (ev.type == EV_MSC && ev.code == MSC_SCAN) {
312                         if (has_scan) {
313                                 fputs("driver did not send SYN event in between key events; previous event:\n",
314                                       stderr);
315                                 print_key(last_scan, last_key, has_scan, has_key);
316                                 has_key = 0;
317                         }
318
319                         last_scan = ev.value;
320                         has_scan = 1;
321                         /*printf("--- got scan %u; has scan %i key %i\n", last_scan, has_scan, has_key); */
322                 }
323                 else if (ev.type == EV_KEY) {
324                         if (has_key) {
325                                 fputs("driver did not send SYN event in between key events; previous event:\n",
326                                       stderr);
327                                 print_key(last_scan, last_key, has_scan, has_key);
328                                 has_scan = 0;
329                         }
330
331                         last_key = ev.code;
332                         has_key = 1 + ev.value;
333                         /*printf("--- got key %hu; has scan %i key %i\n", last_key, has_scan, has_key);*/
334
335                         /* Stop on ESC */
336                         if (ev.code == KEY_ESC && ev.value == 0)
337                                 break;
338                 }
339                 else if (ev.type == EV_SYN) {
340                         /*printf("--- got SYN; has scan %i key %i\n", has_scan, has_key);*/
341                         print_key(last_scan, last_key, has_scan, has_key);
342
343                         has_scan = has_key = 0;
344                 }
345
346         }
347
348         /* release input device */
349         ioctl(fd, EVIOCGRAB, 0);
350 }
351
352 _noreturn_ static void help(int error)
353 {
354         const char* h = "Usage: keymap <event device> [<map file>]\n"
355                         "       keymap <event device> scancode keyname [...]\n"
356                         "       keymap -i <event device>\n";
357         if (error) {
358                 fputs(h, stderr);
359                 exit(2);
360         } else {
361                 fputs(h, stdout);
362                 exit(0);
363         }
364 }
365
366 int main(int argc, char **argv)
367 {
368         static const struct option options[] = {
369                 { "help", no_argument, NULL, 'h' },
370                 { "interactive", no_argument, NULL, 'i' },
371                 {}
372         };
373         int fd = -1;
374         int opt_interactive = 0;
375         int i;
376
377         while (1) {
378                 int option;
379
380                 option = getopt_long(argc, argv, "hi", options, NULL);
381                 if (option == -1)
382                         break;
383
384                 switch (option) {
385                 case 'h':
386                         help(0);
387
388                 case 'i':
389                         opt_interactive = 1;
390                         break;
391                 default:
392                         return 1;
393                 }
394         }
395
396         if (argc < optind+1)
397                 help (1);
398
399         if ((fd = evdev_open(argv[optind])) < 0)
400                 return 3;
401
402         /* one argument (device): dump or interactive */
403         if (argc == optind+1) {
404                 if (opt_interactive)
405                         interactive(fd);
406                 else
407                         dump_table(fd);
408                 return 0;
409         }
410
411         /* two arguments (device, mapfile): set map file */
412         if (argc == optind+2) {
413                 const char *filearg = argv[optind+1];
414                 if (strchr(filearg, '/')) {
415                         /* Keymap file argument is a path */
416                         FILE *f = fopen(filearg, "re");
417                         if (f)
418                                 merge_table(fd, f);
419                         else
420                                 perror(filearg);
421                 } else {
422                         /* Keymap file argument is a filename */
423                         /* Open override file if present, otherwise default file */
424                         char keymap_path[PATH_MAX];
425                         FILE *f;
426                         snprintf(keymap_path, sizeof(keymap_path), "%s%s", SYSCONFDIR "/udev/keymaps/", filearg);
427                         f = fopen(keymap_path, "re");
428                         if (f) {
429                                 merge_table(fd, f);
430                         } else {
431                                 snprintf(keymap_path, sizeof(keymap_path), "%s%s", UDEVLIBEXECDIR "/keymaps/", filearg);
432                                 f = fopen(keymap_path, "re");
433                                 if (f)
434                                         merge_table(fd, f);
435                                 else
436                                         perror(keymap_path);
437                         }
438                 }
439                 return 0;
440         }
441
442         /* more arguments (device, scancode/keyname pairs): set keys directly */
443         if ((argc - optind - 1) % 2 == 0) {
444                 for (i = optind+1; i < argc; i += 2)
445                         set_key(fd, argv[i], argv[i+1]);
446                 return 0;
447         }
448
449         /* invalid number of arguments */
450         help(1);
451         return 1; /* not reached */
452 }