Imported Upstream version 2.0.90
[platform/upstream/kbd.git] / src / setkeycodes.c
1 /*
2  * call: setkeycode scancode keycode ...
3  *  (where scancode is either xx or e0xx, given in hexadecimal,
4  *   and keycode is given in decimal)
5  *
6  * aeb, 941108, 2004-01-11
7  */
8 #include "config.h"
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <sys/ioctl.h>
16 #include <linux/kd.h>
17
18 #include "libcommon.h"
19
20 static void __attribute__((noreturn))
21 usage(char *s)
22 {
23         fprintf(stderr, "setkeycode: %s\n", s);
24         fprintf(stderr, _(
25                             "usage: setkeycode scancode keycode ...\n"
26                             " (where scancode is either xx or e0xx, given in hexadecimal,\n"
27                             "  and keycode is given in decimal)\n"));
28         exit(EXIT_FAILURE);
29 }
30
31 int main(int argc, char **argv)
32 {
33         char *ep;
34         int fd;
35         struct kbkeycode a;
36
37         set_progname(argv[0]);
38         setuplocale();
39
40         if (argc == 2 && !strcmp(argv[1], "-V"))
41                 print_version_and_exit();
42
43         if (argc % 2 != 1)
44                 usage(_("even number of arguments expected"));
45
46         if ((fd = getfd(NULL)) < 0)
47                 kbd_error(EXIT_FAILURE, 0, _("Couldn't get a file descriptor referring to the console"));
48
49         while (argc > 2) {
50                 a.keycode  = atoi(argv[2]);
51                 a.scancode = strtol(argv[1], &ep, 16);
52                 if (*ep)
53                         usage(_("error reading scancode"));
54                 if (a.scancode >= 0xe000) {
55                         a.scancode -= 0xe000;
56                         a.scancode += 128; /* some kernels needed +256 */
57                 }
58 #if 0
59                 /* Test is OK up to 2.5.31--later kernels have more keycodes */
60                 if (a.scancode > 255 || a.keycode > 127)
61                         usage(_("code outside bounds"));
62
63                 /* Both fields are unsigned int, so can be large;
64                    for current kernels the correct test might be
65                      (a.scancode > 255 || a.keycode > 239)
66                    but we can leave testing to the kernel. */
67 #endif
68                 if (ioctl(fd, KDSETKEYCODE, &a)) {
69                         kbd_error(EXIT_FAILURE, errno,
70                                   _("failed to set scancode %x to keycode %d: ioctl KDSETKEYCODE"),
71                                   a.scancode, a.keycode);
72                 }
73                 argc -= 2;
74                 argv += 2;
75         }
76         return EXIT_SUCCESS;
77 }