diff options
Diffstat (limited to 'drivers/input/sparse-keymap.c')
-rw-r--r-- | drivers/input/sparse-keymap.c | 53 |
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 | ||
19 | MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); | 20 | MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); |
20 | MODULE_DESCRIPTION("Generic support for sparse keymaps"); | 21 | MODULE_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 | */ |
179 | void sparse_keymap_free(struct input_dev *dev) | 185 | void 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 | } |
187 | EXPORT_SYMBOL(sparse_keymap_free); | 202 | EXPORT_SYMBOL(sparse_keymap_free); |
188 | 203 | ||