diff options
author | David Härdeman <david@hardeman.nu> | 2015-08-19 20:56:38 +0200 |
---|---|---|
committer | David Härdeman <david@hardeman.nu> | 2015-08-19 20:56:38 +0200 |
commit | 09c3b53ad8795e050b72277968fd50591bbb3a7f (patch) | |
tree | d83bcf26ec55ce585de3a86dd95bd17fe9861e4a /rcm-server-evdev.c | |
parent | f3f7d5445e6f64a7c946f6e0144452952f0809e8 (diff) |
Add support for editing in-kernel keymap
Diffstat (limited to 'rcm-server-evdev.c')
-rw-r--r-- | rcm-server-evdev.c | 77 |
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; |