From b39ddd7a0a083a85639de2bd4638f0b0cfeae013 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 21 Mar 2010 22:56:15 -0700 Subject: [PATCH] --- yaml --- r: 189924 b: refs/heads/master c: 2e2e3b96d98d5c17e9c09bc6088df3e182a71814 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/input/input.c | 9 +++++- trunk/drivers/input/sparse-keymap.c | 50 ++++++++++++++++++----------- 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/[refs] b/[refs] index 95a4a8b9bd82..70bb79aac79c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 13bad37b04c779d98983307a27f97e9caa36f9b1 +refs/heads/master: 2e2e3b96d98d5c17e9c09bc6088df3e182a71814 diff --git a/trunk/drivers/input/input.c b/trunk/drivers/input/input.c index e2aad0a51826..be18fa99fa24 100644 --- a/trunk/drivers/input/input.c +++ b/trunk/drivers/input/input.c @@ -659,7 +659,14 @@ static int input_default_setkeycode(struct input_dev *dev, int input_get_keycode(struct input_dev *dev, unsigned int scancode, unsigned int *keycode) { - return dev->getkeycode(dev, scancode, keycode); + unsigned long flags; + int retval; + + spin_lock_irqsave(&dev->event_lock, flags); + retval = dev->getkeycode(dev, scancode, keycode); + spin_unlock_irqrestore(&dev->event_lock, flags); + + return retval; } EXPORT_SYMBOL(input_get_keycode); diff --git a/trunk/drivers/input/sparse-keymap.c b/trunk/drivers/input/sparse-keymap.c index f64e004935a9..2434ac5d43fe 100644 --- a/trunk/drivers/input/sparse-keymap.c +++ b/trunk/drivers/input/sparse-keymap.c @@ -67,12 +67,14 @@ static int sparse_keymap_getkeycode(struct input_dev *dev, unsigned int scancode, unsigned int *keycode) { - const struct key_entry *key = - sparse_keymap_entry_from_scancode(dev, scancode); + const struct key_entry *key; - if (key && key->type == KE_KEY) { - *keycode = key->keycode; - return 0; + if (dev->keycode) { + key = sparse_keymap_entry_from_scancode(dev, scancode); + if (key && key->type == KE_KEY) { + *keycode = key->keycode; + return 0; + } } return -EINVAL; @@ -85,17 +87,16 @@ static int sparse_keymap_setkeycode(struct input_dev *dev, struct key_entry *key; int old_keycode; - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - - key = sparse_keymap_entry_from_scancode(dev, scancode); - if (key && key->type == KE_KEY) { - old_keycode = key->keycode; - key->keycode = keycode; - set_bit(keycode, dev->keybit); - if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) - clear_bit(old_keycode, dev->keybit); - return 0; + if (dev->keycode) { + key = sparse_keymap_entry_from_scancode(dev, scancode); + if (key && key->type == KE_KEY) { + old_keycode = key->keycode; + key->keycode = keycode; + set_bit(keycode, dev->keybit); + if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) + clear_bit(old_keycode, dev->keybit); + return 0; + } } return -EINVAL; @@ -175,14 +176,27 @@ EXPORT_SYMBOL(sparse_keymap_setup); * * This function is used to free memory allocated by sparse keymap * in an input device that was set up by sparse_keymap_setup(). + * NOTE: It is safe to cal this function while input device is + * still registered (however the drivers should care not to try to + * use freed keymap and thus have to shut off interrups/polling + * before freeing the keymap). */ void sparse_keymap_free(struct input_dev *dev) { + unsigned long flags; + + /* + * Take event lock to prevent racing with input_get_keycode() + * and input_set_keycode() if we are called while input device + * is still registered. + */ + spin_lock_irqsave(&dev->event_lock, flags); + kfree(dev->keycode); dev->keycode = NULL; dev->keycodemax = 0; - dev->getkeycode = NULL; - dev->setkeycode = NULL; + + spin_unlock_irqrestore(&dev->event_lock, flags); } EXPORT_SYMBOL(sparse_keymap_free);