diff options
Diffstat (limited to 'drivers/input/sparse-keymap.c')
-rw-r--r-- | drivers/input/sparse-keymap.c | 52 |
1 files changed, 33 insertions, 19 deletions
diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index 82ae18d29685..014248344763 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c | |||
@@ -68,12 +68,14 @@ static int sparse_keymap_getkeycode(struct input_dev *dev, | |||
68 | unsigned int scancode, | 68 | unsigned int scancode, |
69 | unsigned int *keycode) | 69 | unsigned int *keycode) |
70 | { | 70 | { |
71 | const struct key_entry *key = | 71 | const struct key_entry *key; |
72 | sparse_keymap_entry_from_scancode(dev, scancode); | ||
73 | 72 | ||
74 | if (key && key->type == KE_KEY) { | 73 | if (dev->keycode) { |
75 | *keycode = key->keycode; | 74 | key = sparse_keymap_entry_from_scancode(dev, scancode); |
76 | return 0; | 75 | if (key && key->type == KE_KEY) { |
76 | *keycode = key->keycode; | ||
77 | return 0; | ||
78 | } | ||
77 | } | 79 | } |
78 | 80 | ||
79 | return -EINVAL; | 81 | return -EINVAL; |
@@ -86,17 +88,16 @@ static int sparse_keymap_setkeycode(struct input_dev *dev, | |||
86 | struct key_entry *key; | 88 | struct key_entry *key; |
87 | int old_keycode; | 89 | int old_keycode; |
88 | 90 | ||
89 | if (keycode < 0 || keycode > KEY_MAX) | 91 | if (dev->keycode) { |
90 | return -EINVAL; | 92 | key = sparse_keymap_entry_from_scancode(dev, scancode); |
91 | 93 | if (key && key->type == KE_KEY) { | |
92 | key = sparse_keymap_entry_from_scancode(dev, scancode); | 94 | old_keycode = key->keycode; |
93 | if (key && key->type == KE_KEY) { | 95 | key->keycode = keycode; |
94 | old_keycode = key->keycode; | 96 | set_bit(keycode, dev->keybit); |
95 | key->keycode = keycode; | 97 | if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) |
96 | set_bit(keycode, dev->keybit); | 98 | clear_bit(old_keycode, dev->keybit); |
97 | if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) | 99 | return 0; |
98 | clear_bit(old_keycode, dev->keybit); | 100 | } |
99 | return 0; | ||
100 | } | 101 | } |
101 | 102 | ||
102 | return -EINVAL; | 103 | return -EINVAL; |
@@ -164,7 +165,7 @@ int sparse_keymap_setup(struct input_dev *dev, | |||
164 | return 0; | 165 | return 0; |
165 | 166 | ||
166 | err_out: | 167 | err_out: |
167 | kfree(keymap); | 168 | kfree(map); |
168 | return error; | 169 | return error; |
169 | 170 | ||
170 | } | 171 | } |
@@ -176,14 +177,27 @@ EXPORT_SYMBOL(sparse_keymap_setup); | |||
176 | * | 177 | * |
177 | * This function is used to free memory allocated by sparse keymap | 178 | * This function is used to free memory allocated by sparse keymap |
178 | * 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). | ||
179 | */ | 184 | */ |
180 | void sparse_keymap_free(struct input_dev *dev) | 185 | void sparse_keymap_free(struct input_dev *dev) |
181 | { | 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 | |||
182 | kfree(dev->keycode); | 196 | kfree(dev->keycode); |
183 | dev->keycode = NULL; | 197 | dev->keycode = NULL; |
184 | dev->keycodemax = 0; | 198 | dev->keycodemax = 0; |
185 | dev->getkeycode = NULL; | 199 | |
186 | dev->setkeycode = NULL; | 200 | spin_unlock_irqrestore(&dev->event_lock, flags); |
187 | } | 201 | } |
188 | EXPORT_SYMBOL(sparse_keymap_free); | 202 | EXPORT_SYMBOL(sparse_keymap_free); |
189 | 203 | ||