summaryrefslogtreecommitdiff
path: root/rcm-server-evdev.c
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2015-08-19 20:56:38 +0200
committerDavid Härdeman <david@hardeman.nu>2015-08-19 20:56:38 +0200
commit09c3b53ad8795e050b72277968fd50591bbb3a7f (patch)
treed83bcf26ec55ce585de3a86dd95bd17fe9861e4a /rcm-server-evdev.c
parentf3f7d5445e6f64a7c946f6e0144452952f0809e8 (diff)
Add support for editing in-kernel keymap
Diffstat (limited to 'rcm-server-evdev.c')
-rw-r--r--rcm-server-evdev.c77
1 files changed, 62 insertions, 15 deletions
diff --git a/rcm-server-evdev.c b/rcm-server-evdev.c
index 34014e3..9444b7f 100644
--- a/rcm-server-evdev.c
+++ b/rcm-server-evdev.c
@@ -31,8 +31,8 @@ struct rc_keymap_entry {
__u32 keycode;
union {
struct rc_scancode rc;
- __u8 scancode[32];
- } u;
+ __u8 raw[32];
+ };
char end[];
};
#define RKE_SIZE (sizeof(struct rc_scancode))
@@ -54,21 +54,73 @@ evdev_guess_protocol(struct device *device, uint64_t scancode, uint32_t keycode)
if (ioctl(device->evdev_fd, EVIOCGKEYCODE_V2, &rke))
break;
- if (rke.u.rc.scancode != scancode)
+ if (rke.rc.scancode != scancode)
continue;
if (rke.keycode != keycode)
continue;
- if (rke.u.rc.protocol > ARRAY_SIZE(rc_protocols))
+ if (rke.rc.protocol > ARRAY_SIZE(rc_protocols))
return NULL;
- return rc_protocols[rke.u.rc.protocol];
+ return rc_protocols[rke.rc.protocol];
}
return NULL;
}
+int
+evdev_get_mapping(struct device *device, unsigned index, unsigned *ret_protocol,
+ uint64_t *ret_scancode, struct linux_input_keycode **ret_lik)
+{
+ struct rc_keymap_entry rke;
+ struct linux_input_keycode *lik;
+
+ memset(&rke, 0, sizeof(rke));
+ rke.len = RKE_SIZE;
+ rke.index = index;
+ rke.flags = INPUT_KEYMAP_BY_INDEX;
+
+ if (ioctl(device->evdev_fd, EVIOCGKEYCODE_V2, &rke))
+ return 0;
+
+ lik = get_linux_keycode_by_value(rke.keycode);
+ if (!lik) {
+ printf("unknown keycode: %" PRIu32 "\n", rke.keycode);
+ return -EINVAL;
+ }
+
+ *ret_protocol = rke.rc.protocol;
+ *ret_scancode = rke.rc.scancode;
+ *ret_lik = lik;
+ return 1;
+}
+
+int
+evdev_set_mapping(struct device *device, unsigned protocol, uint64_t scancode,
+ struct linux_input_keycode *lik)
+{
+ struct rc_keymap_entry rke;
+ int r;
+
+ memset(&rke, 0, sizeof(rke));
+ rke.len = RKE_SIZE;
+ rke.rc.protocol = protocol;
+ rke.rc.scancode = scancode;
+
+ if (lik)
+ rke.keycode = lik->value;
+ else
+ rke.keycode = KEY_RESERVED;
+
+ if (ioctl(device->evdev_fd, EVIOCSKEYCODE_V2, &rke)) {
+ r = -errno;
+ printf("EVIOCSKEYCODE_V2 failed (%s)\n", strerror(errno));
+ }
+
+ return r;
+}
+
static int
evdev_clear_keymap(struct device *device)
{
@@ -111,12 +163,12 @@ set_keycode_new(struct device *device, __u16 protocol, __u64 scancode, __u32 key
memset(&rke, 0, sizeof(rke));
rke.len = RKE_SIZE;
- rke.u.rc.protocol = protocol;
- rke.u.rc.scancode = scancode;
+ rke.rc.protocol = protocol;
+ rke.rc.scancode = scancode;
rke.keycode = keycode;
printf("Setting keycode (new ioctl) 0x%08llX (0x%02X) to 0x%02X\n",
- rke.u.rc.scancode, rke.u.rc.protocol, rke.keycode);
+ rke.rc.scancode, rke.rc.protocol, rke.keycode);
if (ioctl(device->evdev_fd, EVIOCSKEYCODE_V2, &rke)) {
printf("Unable to call SETKEYCODE2 ioctl\n");
@@ -150,7 +202,6 @@ evdev_read(sd_event_source *s, int fd, uint32_t revents, void *userdata)
static bool pressed = false;
static uint32_t scancode;
static bool scancode_recv = false;
- unsigned i;
int r;
if (fd != device->evdev_fd)
@@ -183,17 +234,13 @@ evdev_read(sd_event_source *s, int fd, uint32_t revents, void *userdata)
if (keycode)
printf("Reading from evdev - multiple keycodes?\n");
- for (i = 0; linux_input_keycodes[i].name; i++) {
- if (linux_input_keycodes[i].value == ev.code)
- break;
- }
+ keycode = get_linux_keycode_by_value(ev.code);
- if (!linux_input_keycodes[i].name) {
+ if (!keycode) {
printf("evdev - unknown keycode (%u)\n", ev.code);
break;
}
- keycode = &linux_input_keycodes[i];
if (ev.value)
pressed = true;
break;