2 This file is part of systemd.
4 Copyright 2013 Kay Sievers <kay@vrfy.org>
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include <sys/ioctl.h>
26 #include <linux/limits.h>
27 #include <linux/input.h>
31 static const struct key
*keyboard_lookup_key(const char *str
, unsigned int len
);
32 #include "keyboard-keys-from-name.h"
33 #include "keyboard-keys-to-name.h"
35 static int install_force_release(struct udev_device
*dev
, const unsigned int *release
, unsigned int release_count
) {
36 struct udev_device
*atkbd
;
44 atkbd
= udev_device_get_parent_with_subsystem_devtype(dev
, "serio", NULL
);
48 cur
= udev_device_get_sysattr_value(atkbd
, "force_release");
55 /* copy current content */
56 l
= strpcpy(&s
, l
, cur
);
58 /* append new codes */
59 for (i
= 0; i
< release_count
; i
++)
60 l
= strpcpyf(&s
, l
, ",%d", release
[i
]);
62 log_debug("keyboard: updating force-release list with '%s'\n", codes
);
63 ret
= udev_device_set_sysattr_value(atkbd
, "force_release", codes
);
65 log_error("Error writing force-release attribute: %s", strerror(-ret
));
69 static int builtin_keyboard(struct udev_device
*dev
, int argc
, char *argv
[], bool test
) {
70 struct udev_list_entry
*entry
;
75 unsigned int map_count
= 0;
76 unsigned int release
[1024];
77 unsigned int release_count
= 0;
79 udev_list_entry_foreach(entry
, udev_device_get_properties_list_entry(dev
)) {
81 unsigned int scancode
;
86 key
= udev_list_entry_get_name(entry
);
87 if (!startswith(key
, "KEYBOARD_KEY_"))
90 /* KEYBOARD_KEY_<hex scan code>=<key identifier string> */
91 scancode
= strtol(key
+ 13, &endptr
, 16);
92 if (endptr
[0] != '\0') {
93 log_error("Error, unable to parse scan code from '%s'\n", key
);
97 keycode
= udev_list_entry_get_value(entry
);
99 /* a leading '!' needs a force-release entry */
100 if (keycode
[0] == '!') {
103 release
[release_count
] = scancode
;
104 if (release_count
< ELEMENTSOF(release
)-1)
107 if (keycode
[0] == '\0')
111 /* translate identifier to key code */
112 k
= keyboard_lookup_key(keycode
, strlen(keycode
));
114 log_error("Error, unknown key identifier '%s'\n", keycode
);
118 map
[map_count
].scan
= scancode
;
119 map
[map_count
].key
= k
->id
;
120 if (map_count
< ELEMENTSOF(map
)-1)
124 if (map_count
> 0 || release_count
> 0) {
129 node
= udev_device_get_devnode(dev
);
131 log_error("Error, no device node for '%s'\n", udev_device_get_syspath(dev
));
135 fd
= open(udev_device_get_devnode(dev
), O_RDWR
|O_CLOEXEC
|O_NONBLOCK
|O_NOCTTY
);
137 log_error("Error, opening device '%s': %m\n", node
);
141 /* install list of map codes */
142 for (i
= 0; i
< map_count
; i
++) {
143 log_debug("keyboard: mapping scan code %d (0x%x) to key code %d (0x%x)\n",
144 map
[i
].scan
, map
[i
].scan
, map
[i
].key
, map
[i
].key
);
145 if (ioctl(fd
, EVIOCSKEYCODE
, &map
[i
]) < 0)
146 log_error("Error calling EVIOCSKEYCODE: %m\n");
149 /* install list of force-release codes */
150 if (release_count
> 0)
151 install_force_release(dev
, release
, release_count
);
159 const struct udev_builtin udev_builtin_keyboard
= {
161 .cmd
= builtin_keyboard
,
162 .help
= "keyboard scan code to key mapping",