diff options
author | Anisse Astier <anisse@astier.eu> | 2009-12-10 08:18:19 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-12-16 12:40:54 -0500 |
commit | c30116c6f0d26cd6e46dfa578163d573ef4730b2 (patch) | |
tree | 8a7d227ebfad69c0f877343bd2c603e3e94b57b0 /drivers/platform/x86/msi-wmi.c | |
parent | d607af93006594f7da1d4b7d44724c5308f4e892 (diff) |
msi-wmi: switch to using input sparse keymap library
Signed-off-by: Anisse Astier <anisse@astier.eu>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/platform/x86/msi-wmi.c')
-rw-r--r-- | drivers/platform/x86/msi-wmi.c | 134 |
1 files changed, 32 insertions, 102 deletions
diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index 2c2afc1828b8..e25b80c530f7 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c | |||
@@ -21,9 +21,9 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | 23 | ||
24 | |||
25 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
26 | #include <linux/input.h> | 25 | #include <linux/input.h> |
26 | #include <linux/input/sparse-keymap.h> | ||
27 | #include <linux/acpi.h> | 27 | #include <linux/acpi.h> |
28 | #include <linux/backlight.h> | 28 | #include <linux/backlight.h> |
29 | 29 | ||
@@ -52,26 +52,15 @@ MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-6638:*"); | |||
52 | 52 | ||
53 | #define dprintk(msg...) pr_debug(DRV_PFX msg) | 53 | #define dprintk(msg...) pr_debug(DRV_PFX msg) |
54 | 54 | ||
55 | struct key_entry { | 55 | #define KEYCODE_BASE 0xD0 |
56 | char type; /* See KE_* below */ | ||
57 | u16 code; | ||
58 | u16 keycode; | ||
59 | ktime_t last_pressed; | ||
60 | }; | ||
61 | |||
62 | /* | ||
63 | * KE_KEY the only used key type, but keep this, others might also | ||
64 | * show up in the future. Compare with hp-wmi.c | ||
65 | */ | ||
66 | enum { KE_KEY, KE_END }; | ||
67 | |||
68 | static struct key_entry msi_wmi_keymap[] = { | 56 | static struct key_entry msi_wmi_keymap[] = { |
69 | { KE_KEY, 0xd0, KEY_BRIGHTNESSUP, {0, } }, | 57 | { KE_KEY, KEYCODE_BASE, {KEY_BRIGHTNESSUP} }, |
70 | { KE_KEY, 0xd1, KEY_BRIGHTNESSDOWN, {0, } }, | 58 | { KE_KEY, KEYCODE_BASE + 1, {KEY_BRIGHTNESSDOWN} }, |
71 | { KE_KEY, 0xd2, KEY_VOLUMEUP, {0, } }, | 59 | { KE_KEY, KEYCODE_BASE + 2, {KEY_VOLUMEUP} }, |
72 | { KE_KEY, 0xd3, KEY_VOLUMEDOWN, {0, } }, | 60 | { KE_KEY, KEYCODE_BASE + 3, {KEY_VOLUMEDOWN} }, |
73 | { KE_END, 0} | 61 | { KE_END, 0} |
74 | }; | 62 | }; |
63 | static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1]; | ||
75 | 64 | ||
76 | struct backlight_device *backlight; | 65 | struct backlight_device *backlight; |
77 | 66 | ||
@@ -158,61 +147,6 @@ static struct backlight_ops msi_backlight_ops = { | |||
158 | .update_status = bl_set_status, | 147 | .update_status = bl_set_status, |
159 | }; | 148 | }; |
160 | 149 | ||
161 | static struct key_entry *msi_wmi_get_entry_by_scancode(int code) | ||
162 | { | ||
163 | struct key_entry *key; | ||
164 | |||
165 | for (key = msi_wmi_keymap; key->type != KE_END; key++) | ||
166 | if (code == key->code) | ||
167 | return key; | ||
168 | |||
169 | return NULL; | ||
170 | } | ||
171 | |||
172 | static struct key_entry *msi_wmi_get_entry_by_keycode(int keycode) | ||
173 | { | ||
174 | struct key_entry *key; | ||
175 | |||
176 | for (key = msi_wmi_keymap; key->type != KE_END; key++) | ||
177 | if (key->type == KE_KEY && keycode == key->keycode) | ||
178 | return key; | ||
179 | |||
180 | return NULL; | ||
181 | } | ||
182 | |||
183 | static int msi_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode) | ||
184 | { | ||
185 | struct key_entry *key = msi_wmi_get_entry_by_scancode(scancode); | ||
186 | |||
187 | if (key && key->type == KE_KEY) { | ||
188 | *keycode = key->keycode; | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | return -EINVAL; | ||
193 | } | ||
194 | |||
195 | static int msi_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode) | ||
196 | { | ||
197 | struct key_entry *key; | ||
198 | int old_keycode; | ||
199 | |||
200 | if (keycode < 0 || keycode > KEY_MAX) | ||
201 | return -EINVAL; | ||
202 | |||
203 | key = msi_wmi_get_entry_by_scancode(scancode); | ||
204 | if (key && key->type == KE_KEY) { | ||
205 | old_keycode = key->keycode; | ||
206 | key->keycode = keycode; | ||
207 | set_bit(keycode, dev->keybit); | ||
208 | if (!msi_wmi_get_entry_by_keycode(old_keycode)) | ||
209 | clear_bit(old_keycode, dev->keybit); | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | return -EINVAL; | ||
214 | } | ||
215 | |||
216 | static void msi_wmi_notify(u32 value, void *context) | 150 | static void msi_wmi_notify(u32 value, void *context) |
217 | { | 151 | { |
218 | struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; | 152 | struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; |
@@ -227,21 +161,22 @@ static void msi_wmi_notify(u32 value, void *context) | |||
227 | if (obj && obj->type == ACPI_TYPE_INTEGER) { | 161 | if (obj && obj->type == ACPI_TYPE_INTEGER) { |
228 | int eventcode = obj->integer.value; | 162 | int eventcode = obj->integer.value; |
229 | dprintk("Eventcode: 0x%x\n", eventcode); | 163 | dprintk("Eventcode: 0x%x\n", eventcode); |
230 | key = msi_wmi_get_entry_by_scancode(eventcode); | 164 | key = sparse_keymap_entry_from_scancode(msi_wmi_input_dev, |
165 | eventcode); | ||
231 | if (key) { | 166 | if (key) { |
167 | ktime_t diff; | ||
232 | cur = ktime_get_real(); | 168 | cur = ktime_get_real(); |
169 | diff = ktime_sub(cur, last_pressed[key->code - | ||
170 | KEYCODE_BASE]); | ||
233 | /* Ignore event if the same event happened in a 50 ms | 171 | /* Ignore event if the same event happened in a 50 ms |
234 | timeframe -> Key press may result in 10-20 GPEs */ | 172 | timeframe -> Key press may result in 10-20 GPEs */ |
235 | if (ktime_to_us(ktime_sub(cur, key->last_pressed)) | 173 | if (ktime_to_us(diff) < 1000 * 50) { |
236 | < 1000 * 50) { | ||
237 | dprintk("Suppressed key event 0x%X - " | 174 | dprintk("Suppressed key event 0x%X - " |
238 | "Last press was %lld us ago\n", | 175 | "Last press was %lld us ago\n", |
239 | key->code, | 176 | key->code, ktime_to_us(diff)); |
240 | ktime_to_us(ktime_sub(cur, | ||
241 | key->last_pressed))); | ||
242 | return; | 177 | return; |
243 | } | 178 | } |
244 | key->last_pressed = cur; | 179 | last_pressed[key->code - KEYCODE_BASE] = cur; |
245 | 180 | ||
246 | if (key->type == KE_KEY && | 181 | if (key->type == KE_KEY && |
247 | /* Brightness is served via acpi video driver */ | 182 | /* Brightness is served via acpi video driver */ |
@@ -250,12 +185,8 @@ static void msi_wmi_notify(u32 value, void *context) | |||
250 | dprintk("Send key: 0x%X - " | 185 | dprintk("Send key: 0x%X - " |
251 | "Input layer keycode: %d\n", key->code, | 186 | "Input layer keycode: %d\n", key->code, |
252 | key->keycode); | 187 | key->keycode); |
253 | input_report_key(msi_wmi_input_dev, | 188 | sparse_keymap_report_entry(msi_wmi_input_dev, |
254 | key->keycode, 1); | 189 | key, 1, true); |
255 | input_sync(msi_wmi_input_dev); | ||
256 | input_report_key(msi_wmi_input_dev, | ||
257 | key->keycode, 0); | ||
258 | input_sync(msi_wmi_input_dev); | ||
259 | } | 190 | } |
260 | } else | 191 | } else |
261 | printk(KERN_INFO "Unknown key pressed - %x\n", | 192 | printk(KERN_INFO "Unknown key pressed - %x\n", |
@@ -267,7 +198,6 @@ static void msi_wmi_notify(u32 value, void *context) | |||
267 | 198 | ||
268 | static int __init msi_wmi_input_setup(void) | 199 | static int __init msi_wmi_input_setup(void) |
269 | { | 200 | { |
270 | struct key_entry *key; | ||
271 | int err; | 201 | int err; |
272 | 202 | ||
273 | msi_wmi_input_dev = input_allocate_device(); | 203 | msi_wmi_input_dev = input_allocate_device(); |
@@ -277,26 +207,25 @@ static int __init msi_wmi_input_setup(void) | |||
277 | msi_wmi_input_dev->name = "MSI WMI hotkeys"; | 207 | msi_wmi_input_dev->name = "MSI WMI hotkeys"; |
278 | msi_wmi_input_dev->phys = "wmi/input0"; | 208 | msi_wmi_input_dev->phys = "wmi/input0"; |
279 | msi_wmi_input_dev->id.bustype = BUS_HOST; | 209 | msi_wmi_input_dev->id.bustype = BUS_HOST; |
280 | msi_wmi_input_dev->getkeycode = msi_wmi_getkeycode; | 210 | |
281 | msi_wmi_input_dev->setkeycode = msi_wmi_setkeycode; | 211 | err = sparse_keymap_setup(msi_wmi_input_dev, msi_wmi_keymap, NULL); |
282 | 212 | if (err) | |
283 | for (key = msi_wmi_keymap; key->type != KE_END; key++) { | 213 | goto err_free_dev; |
284 | switch (key->type) { | ||
285 | case KE_KEY: | ||
286 | set_bit(EV_KEY, msi_wmi_input_dev->evbit); | ||
287 | set_bit(key->keycode, msi_wmi_input_dev->keybit); | ||
288 | break; | ||
289 | } | ||
290 | } | ||
291 | 214 | ||
292 | err = input_register_device(msi_wmi_input_dev); | 215 | err = input_register_device(msi_wmi_input_dev); |
293 | 216 | ||
294 | if (err) { | 217 | if (err) |
295 | input_free_device(msi_wmi_input_dev); | 218 | goto err_free_keymap; |
296 | return err; | 219 | |
297 | } | 220 | memset(last_pressed, 0, sizeof(last_pressed)); |
298 | 221 | ||
299 | return 0; | 222 | return 0; |
223 | |||
224 | err_free_keymap: | ||
225 | sparse_keymap_free(msi_wmi_input_dev); | ||
226 | err_free_dev: | ||
227 | input_free_device(msi_wmi_input_dev); | ||
228 | return err; | ||
300 | } | 229 | } |
301 | 230 | ||
302 | static int __init msi_wmi_init(void) | 231 | static int __init msi_wmi_init(void) |
@@ -347,6 +276,7 @@ static void __exit msi_wmi_exit(void) | |||
347 | { | 276 | { |
348 | if (wmi_has_guid(MSIWMI_EVENT_GUID)) { | 277 | if (wmi_has_guid(MSIWMI_EVENT_GUID)) { |
349 | wmi_remove_notify_handler(MSIWMI_EVENT_GUID); | 278 | wmi_remove_notify_handler(MSIWMI_EVENT_GUID); |
279 | sparse_keymap_free(msi_wmi_input_dev); | ||
350 | input_unregister_device(msi_wmi_input_dev); | 280 | input_unregister_device(msi_wmi_input_dev); |
351 | backlight_device_unregister(backlight); | 281 | backlight_device_unregister(backlight); |
352 | } | 282 | } |