aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/sparse-keymap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/sparse-keymap.c')
-rw-r--r--drivers/input/sparse-keymap.c53
1 files changed, 34 insertions, 19 deletions
diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c
index e6bde55e5203..014248344763 100644
--- a/drivers/input/sparse-keymap.c
+++ b/drivers/input/sparse-keymap.c
@@ -15,6 +15,7 @@
15 15
16#include <linux/input.h> 16#include <linux/input.h>
17#include <linux/input/sparse-keymap.h> 17#include <linux/input/sparse-keymap.h>
18#include <linux/slab.h>
18 19
19MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); 20MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
20MODULE_DESCRIPTION("Generic support for sparse keymaps"); 21MODULE_DESCRIPTION("Generic support for sparse keymaps");
@@ -67,12 +68,14 @@ static int sparse_keymap_getkeycode(struct input_dev *dev,
67 unsigned int scancode, 68 unsigned int scancode,
68 unsigned int *keycode) 69 unsigned int *keycode)
69{ 70{
70 const struct key_entry *key = 71 const struct key_entry *key;
71 sparse_keymap_entry_from_scancode(dev, scancode);
72 72
73 if (key && key->type == KE_KEY) { 73 if (dev->keycode) {
74 *keycode = key->keycode; 74 key = sparse_keymap_entry_from_scancode(dev, scancode);
75 return 0; 75 if (key && key->type == KE_KEY) {
76 *keycode = key->keycode;
77 return 0;
78 }
76 } 79 }
77 80
78 return -EINVAL; 81 return -EINVAL;
@@ -85,17 +88,16 @@ static int sparse_keymap_setkeycode(struct input_dev *dev,
85 struct key_entry *key; 88 struct key_entry *key;
86 int old_keycode; 89 int old_keycode;
87 90
88 if (keycode < 0 || keycode > KEY_MAX) 91 if (dev->keycode) {
89 return -EINVAL; 92 key = sparse_keymap_entry_from_scancode(dev, scancode);
90 93 if (key && key->type == KE_KEY) {
91 key = sparse_keymap_entry_from_scancode(dev, scancode); 94 old_keycode = key->keycode;
92 if (key && key->type == KE_KEY) { 95 key->keycode = keycode;
93 old_keycode = key->keycode; 96 set_bit(keycode, dev->keybit);
94 key->keycode = keycode; 97 if (!sparse_keymap_entry_from_keycode(dev, old_keycode))
95 set_bit(keycode, dev->keybit); 98 clear_bit(old_keycode, dev->keybit);
96 if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) 99 return 0;
97 clear_bit(old_keycode, dev->keybit); 100 }
98 return 0;
99 } 101 }
100 102
101 return -EINVAL; 103 return -EINVAL;
@@ -163,7 +165,7 @@ int sparse_keymap_setup(struct input_dev *dev,
163 return 0; 165 return 0;
164 166
165 err_out: 167 err_out:
166 kfree(keymap); 168 kfree(map);
167 return error; 169 return error;
168 170
169} 171}
@@ -175,14 +177,27 @@ EXPORT_SYMBOL(sparse_keymap_setup);
175 * 177 *
176 * This function is used to free memory allocated by sparse keymap 178 * This function is used to free memory allocated by sparse keymap
177 * in an input device that was set up by sparse_keymap_setup(). 179 * in an input device that was set up by sparse_keymap_setup().
180 * NOTE: It is safe to cal this function while input device is
181 * still registered (however the drivers should care not to try to
182 * use freed keymap and thus have to shut off interrups/polling
183 * before freeing the keymap).
178 */ 184 */
179void sparse_keymap_free(struct input_dev *dev) 185void sparse_keymap_free(struct input_dev *dev)
180{ 186{
187 unsigned long flags;
188
189 /*
190 * Take event lock to prevent racing with input_get_keycode()
191 * and input_set_keycode() if we are called while input device
192 * is still registered.
193 */
194 spin_lock_irqsave(&dev->event_lock, flags);
195
181 kfree(dev->keycode); 196 kfree(dev->keycode);
182 dev->keycode = NULL; 197 dev->keycode = NULL;
183 dev->keycodemax = 0; 198 dev->keycodemax = 0;
184 dev->getkeycode = NULL; 199
185 dev->setkeycode = NULL; 200 spin_unlock_irqrestore(&dev->event_lock, flags);
186} 201}
187EXPORT_SYMBOL(sparse_keymap_free); 202EXPORT_SYMBOL(sparse_keymap_free);
188 203