diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-09-09 21:54:22 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-09-09 22:00:50 -0700 |
commit | 8613e4c2872a87cc309a42de2c7091744dc54d0e (patch) | |
tree | 75b6513268aca8b614f3b2a55421c7a07b4a9899 /drivers/char/keyboard.c | |
parent | a4e6aad64735702256e4feaa4724eb776ca4e637 (diff) |
Input: add support for large scancodes
Several devices use a high number of bits for scancodes. One important
group is the Remote Controllers. Some new protocols like RC-6 define a
scancode space of 64 bits.
The current EVIO[CS]GKEYCODE ioctls allow replace the scancode/keycode
translation tables, but it is limited to up to 32 bits for scancode.
Also, if userspace wants to clean the existing table, replacing it by
a new one, it needs to run a loop calling the ioctls over the entire
sparse scancode space.
To solve those problems, this patch extends the ioctls to allow drivers
handle scancodes up to 32 bytes long (the length could be extended in
the future should such need arise) and allow userspace to query and set
scancode to keycode mappings not only by scancode but also by index.
Compatibility code were also added to handle the old format of
EVIO[CS]GKEYCODE ioctls.
Folded fixes by:
- Dan Carpenter: locking fixes for the original implementation
- Jarod Wilson: fix crash when setting keycode and wiring up get/set
handlers in original implementation.
- Dmitry Torokhov: rework to consolidate old and new scancode handling,
provide options to act either by index or scancode.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Dan Carpenter <error27@gmail.com>
Signed-off-by: Jarod Wilson <jarod@redhat.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/char/keyboard.c')
-rw-r--r-- | drivers/char/keyboard.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index a7ca75212bf..e95d7876ca6 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -175,8 +175,7 @@ EXPORT_SYMBOL_GPL(unregister_keyboard_notifier); */ struct getset_keycode_data { - unsigned int scancode; - unsigned int keycode; + struct input_keymap_entry ke; int error; }; @@ -184,32 +183,50 @@ static int getkeycode_helper(struct input_handle *handle, void *data) { struct getset_keycode_data *d = data; - d->error = input_get_keycode(handle->dev, d->scancode, &d->keycode); + d->error = input_get_keycode(handle->dev, &d->ke); return d->error == 0; /* stop as soon as we successfully get one */ } int getkeycode(unsigned int scancode) { - struct getset_keycode_data d = { scancode, 0, -ENODEV }; + struct getset_keycode_data d = { + .ke = { + .flags = 0, + .len = sizeof(scancode), + .keycode = 0, + }, + .error = -ENODEV, + }; + + memcpy(d.ke.scancode, &scancode, sizeof(scancode)); input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper); - return d.error ?: d.keycode; + return d.error ?: d.ke.keycode; } static int setkeycode_helper(struct input_handle *handle, void *data) { struct getset_keycode_data *d = data; - d->error = input_set_keycode(handle->dev, d->scancode, d->keycode); + d->error = input_set_keycode(handle->dev, &d->ke); return d->error == 0; /* stop as soon as we successfully set one */ } int setkeycode(unsigned int scancode, unsigned int keycode) { - struct getset_keycode_data d = { scancode, keycode, -ENODEV }; + struct getset_keycode_data d = { + .ke = { + .flags = 0, + .len = sizeof(scancode), + .keycode = keycode, + }, + .error = -ENODEV, + }; + + memcpy(d.ke.scancode, &scancode, sizeof(scancode)); input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper); |