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