From f4f37c8ec7d2491c8885c890ba74254b9adfbeee Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 4 Nov 2007 00:41:12 -0400 Subject: Input: Add proper locking when changing device's keymap Take dev->event_lock to make sure that we don't race with input_event() and also force key up event when removing a key from keymap table. Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 6 deletions(-) (limited to 'drivers/input/input.c') diff --git a/drivers/input/input.c b/drivers/input/input.c index a0be978501f..e1729e1dd9b 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -493,7 +493,7 @@ static void input_disconnect_device(struct input_dev *dev) if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) { for (code = 0; code <= KEY_MAX; code++) { if (is_event_supported(code, dev->keybit, KEY_MAX) && - test_bit(code, dev->key)) { + __test_and_clear_bit(code, dev->key)) { input_pass_event(dev, EV_KEY, code, 0); } } @@ -526,7 +526,7 @@ static int input_default_getkeycode(struct input_dev *dev, if (!dev->keycodesize) return -EINVAL; - if (scancode < 0 || scancode >= dev->keycodemax) + if (scancode >= dev->keycodemax) return -EINVAL; *keycode = input_fetch_keycode(dev, scancode); @@ -540,10 +540,7 @@ static int input_default_setkeycode(struct input_dev *dev, int old_keycode; int i; - if (scancode < 0 || scancode >= dev->keycodemax) - return -EINVAL; - - if (keycode < 0 || keycode > KEY_MAX) + if (scancode >= dev->keycodemax) return -EINVAL; if (!dev->keycodesize) @@ -586,6 +583,75 @@ static int input_default_setkeycode(struct input_dev *dev, return 0; } +/** + * input_get_keycode - retrieve keycode currently mapped to a given scancode + * @dev: input device which keymap is being queried + * @scancode: scancode (or its equivalent for device in question) for which + * keycode is needed + * @keycode: result + * + * This function should be called by anyone interested in retrieving current + * keymap. Presently keyboard and evdev handlers use it. + */ +int input_get_keycode(struct input_dev *dev, int scancode, int *keycode) +{ + if (scancode < 0) + return -EINVAL; + + return dev->getkeycode(dev, scancode, keycode); +} +EXPORT_SYMBOL(input_get_keycode); + +/** + * input_get_keycode - assign new keycode to a given scancode + * @dev: input device which keymap is being updated + * @scancode: scancode (or its equivalent for device in question) + * @keycode: new keycode to be assigned to the scancode + * + * This function should be called by anyone needing to update current + * keymap. Presently keyboard and evdev handlers use it. + */ +int input_set_keycode(struct input_dev *dev, int scancode, int keycode) +{ + unsigned long flags; + int old_keycode; + int retval; + + if (scancode < 0) + return -EINVAL; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + spin_lock_irqsave(&dev->event_lock, flags); + + retval = dev->getkeycode(dev, scancode, &old_keycode); + if (retval) + goto out; + + retval = dev->setkeycode(dev, scancode, keycode); + if (retval) + goto out; + + /* + * Simulate keyup event if keycode is not present + * in the keymap anymore + */ + if (test_bit(EV_KEY, dev->evbit) && + !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && + __test_and_clear_bit(old_keycode, dev->key)) { + + input_pass_event(dev, EV_KEY, old_keycode, 0); + if (dev->sync) + input_pass_event(dev, EV_SYN, SYN_REPORT, 1); + } + + out: + spin_unlock_irqrestore(&dev->event_lock, flags); + + return retval; +} +EXPORT_SYMBOL(input_set_keycode); #define MATCH_BIT(bit, max) \ for (i = 0; i < BITS_TO_LONGS(max); i++) \ -- cgit v1.2.3 From 0c1efd365306c9b04df5abdd41e9b4dc721e84fb Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 21 Jan 2008 01:08:24 -0500 Subject: Input: remove cdev from input_dev structure Cdev field was obsolete and provided only for backward compatibility since conversion of input core from class devices to regular devices. It is time to remove it. Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/input/input.c') diff --git a/drivers/input/input.c b/drivers/input/input.c index e1729e1dd9b..6ee8af8963f 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1395,9 +1395,6 @@ int input_register_device(struct input_dev *dev) snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); - if (dev->cdev.dev) - dev->dev.parent = dev->cdev.dev; - error = device_add(&dev->dev); if (error) return error; -- cgit v1.2.3 From cec69c376be132a6afdc55b8090a389eaa3cd770 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 31 Jan 2008 00:43:32 -0500 Subject: Input: constify function pointer tables (seq_operations) Signed-off-by: Jan Engelhardt Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input/input.c') diff --git a/drivers/input/input.c b/drivers/input/input.c index 6ee8af8963f..f02c242c311 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -821,7 +821,7 @@ static int input_devices_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations input_devices_seq_ops = { +static const struct seq_operations input_devices_seq_ops = { .start = input_devices_seq_start, .next = input_devices_seq_next, .stop = input_devices_seq_stop, @@ -874,7 +874,7 @@ static int input_handlers_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations input_handlers_seq_ops = { +static const struct seq_operations input_handlers_seq_ops = { .start = input_handlers_seq_start, .next = input_handlers_seq_next, .stop = input_handlers_seq_stop, -- cgit v1.2.3