aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2010-08-05 01:30:13 -0400
committerMatthew Garrett <mjg@redhat.com>2010-10-21 09:36:43 -0400
commit4d291ed7217d617dacbf54b4bd35819b0d08b981 (patch)
tree8bb47a2fb8eb1117f3f59f137ecc2a477b5bf940 /drivers/platform
parent890a7c8e8dc2d0890e795bda9ad3484ebac42c0b (diff)
Input: hp-wmi - switch to using sparse keymap library
Instead of implementing its own version of keymap hanlding switch over to using sparse keymap library. Also make sure that we install notify handler only after we allocated input device and that we remove notify handler before unregistering input device. Signed-off-by: Dmitry Torokhov <dtor@mail.ru> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/Kconfig1
-rw-r--r--drivers/platform/x86/hp-wmi.c172
2 files changed, 52 insertions, 121 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index ee8b09eb70fd..1ca392f5c826 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -141,6 +141,7 @@ config HP_WMI
141 depends on ACPI_WMI 141 depends on ACPI_WMI
142 depends on INPUT 142 depends on INPUT
143 depends on RFKILL || RFKILL = n 143 depends on RFKILL || RFKILL = n
144 select INPUT_SPARSEKMAP
144 help 145 help
145 Say Y here if you want to support WMI-based hotkeys on HP laptops and 146 Say Y here if you want to support WMI-based hotkeys on HP laptops and
146 to read data from WMI such as docking or ambient light sensor state. 147 to read data from WMI such as docking or ambient light sensor state.
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index c1741142a4cb..1dac659b5e0c 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -29,6 +29,7 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/types.h> 30#include <linux/types.h>
31#include <linux/input.h> 31#include <linux/input.h>
32#include <linux/input/sparse-keymap.h>
32#include <linux/platform_device.h> 33#include <linux/platform_device.h>
33#include <linux/acpi.h> 34#include <linux/acpi.h>
34#include <linux/rfkill.h> 35#include <linux/rfkill.h>
@@ -88,24 +89,16 @@ struct bios_return {
88 u32 value; 89 u32 value;
89}; 90};
90 91
91struct key_entry { 92static const struct key_entry hp_wmi_keymap[] = {
92 char type; /* See KE_* below */ 93 { KE_KEY, 0x02, { KEY_BRIGHTNESSUP } },
93 u16 code; 94 { KE_KEY, 0x03, { KEY_BRIGHTNESSDOWN } },
94 u16 keycode; 95 { KE_KEY, 0x20e6, { KEY_PROG1 } },
95}; 96 { KE_KEY, 0x20e8, { KEY_MEDIA } },
96 97 { KE_KEY, 0x2142, { KEY_MEDIA } },
97enum { KE_KEY, KE_END }; 98 { KE_KEY, 0x213b, { KEY_INFO } },
98 99 { KE_KEY, 0x2169, { KEY_DIRECTION } },
99static struct key_entry hp_wmi_keymap[] = { 100 { KE_KEY, 0x231b, { KEY_HELP } },
100 {KE_KEY, 0x02, KEY_BRIGHTNESSUP}, 101 { KE_END, 0 }
101 {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
102 {KE_KEY, 0x20e6, KEY_PROG1},
103 {KE_KEY, 0x20e8, KEY_MEDIA},
104 {KE_KEY, 0x2142, KEY_MEDIA},
105 {KE_KEY, 0x213b, KEY_INFO},
106 {KE_KEY, 0x2169, KEY_DIRECTION},
107 {KE_KEY, 0x231b, KEY_HELP},
108 {KE_END, 0}
109}; 102};
110 103
111static struct input_dev *hp_wmi_input_dev; 104static struct input_dev *hp_wmi_input_dev;
@@ -347,64 +340,9 @@ static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als);
347static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); 340static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL);
348static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL); 341static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL);
349 342
350static struct key_entry *hp_wmi_get_entry_by_scancode(unsigned int code)
351{
352 struct key_entry *key;
353
354 for (key = hp_wmi_keymap; key->type != KE_END; key++)
355 if (code == key->code)
356 return key;
357
358 return NULL;
359}
360
361static struct key_entry *hp_wmi_get_entry_by_keycode(unsigned int keycode)
362{
363 struct key_entry *key;
364
365 for (key = hp_wmi_keymap; key->type != KE_END; key++)
366 if (key->type == KE_KEY && keycode == key->keycode)
367 return key;
368
369 return NULL;
370}
371
372static int hp_wmi_getkeycode(struct input_dev *dev,
373 unsigned int scancode, unsigned int *keycode)
374{
375 struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode);
376
377 if (key && key->type == KE_KEY) {
378 *keycode = key->keycode;
379 return 0;
380 }
381
382 return -EINVAL;
383}
384
385static int hp_wmi_setkeycode(struct input_dev *dev,
386 unsigned int scancode, unsigned int keycode)
387{
388 struct key_entry *key;
389 unsigned int old_keycode;
390
391 key = hp_wmi_get_entry_by_scancode(scancode);
392 if (key && key->type == KE_KEY) {
393 old_keycode = key->keycode;
394 key->keycode = keycode;
395 set_bit(keycode, dev->keybit);
396 if (!hp_wmi_get_entry_by_keycode(old_keycode))
397 clear_bit(old_keycode, dev->keybit);
398 return 0;
399 }
400
401 return -EINVAL;
402}
403
404static void hp_wmi_notify(u32 value, void *context) 343static void hp_wmi_notify(u32 value, void *context)
405{ 344{
406 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 345 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
407 static struct key_entry *key;
408 union acpi_object *obj; 346 union acpi_object *obj;
409 u32 event_id, event_data; 347 u32 event_id, event_data;
410 int key_code = 0, ret; 348 int key_code = 0, ret;
@@ -465,19 +403,9 @@ static void hp_wmi_notify(u32 value, void *context)
465 sizeof(key_code)); 403 sizeof(key_code));
466 if (ret) 404 if (ret)
467 break; 405 break;
468 key = hp_wmi_get_entry_by_scancode(key_code); 406
469 if (key) { 407 if (!sparse_keymap_report_event(hp_wmi_input_dev,
470 switch (key->type) { 408 key_code, 1, true))
471 case KE_KEY:
472 input_report_key(hp_wmi_input_dev,
473 key->keycode, 1);
474 input_sync(hp_wmi_input_dev);
475 input_report_key(hp_wmi_input_dev,
476 key->keycode, 0);
477 input_sync(hp_wmi_input_dev);
478 break;
479 }
480 } else
481 printk(KERN_INFO PREFIX "Unknown key code - 0x%x\n", 409 printk(KERN_INFO PREFIX "Unknown key code - 0x%x\n",
482 key_code); 410 key_code);
483 break; 411 break;
@@ -510,7 +438,7 @@ static void hp_wmi_notify(u32 value, void *context)
510 438
511static int __init hp_wmi_input_setup(void) 439static int __init hp_wmi_input_setup(void)
512{ 440{
513 struct key_entry *key; 441 acpi_status status;
514 int err; 442 int err;
515 443
516 hp_wmi_input_dev = input_allocate_device(); 444 hp_wmi_input_dev = input_allocate_device();
@@ -520,21 +448,14 @@ static int __init hp_wmi_input_setup(void)
520 hp_wmi_input_dev->name = "HP WMI hotkeys"; 448 hp_wmi_input_dev->name = "HP WMI hotkeys";
521 hp_wmi_input_dev->phys = "wmi/input0"; 449 hp_wmi_input_dev->phys = "wmi/input0";
522 hp_wmi_input_dev->id.bustype = BUS_HOST; 450 hp_wmi_input_dev->id.bustype = BUS_HOST;
523 hp_wmi_input_dev->getkeycode = hp_wmi_getkeycode;
524 hp_wmi_input_dev->setkeycode = hp_wmi_setkeycode;
525
526 for (key = hp_wmi_keymap; key->type != KE_END; key++) {
527 switch (key->type) {
528 case KE_KEY:
529 set_bit(EV_KEY, hp_wmi_input_dev->evbit);
530 set_bit(key->keycode, hp_wmi_input_dev->keybit);
531 break;
532 }
533 }
534 451
535 set_bit(EV_SW, hp_wmi_input_dev->evbit); 452 __set_bit(EV_SW, hp_wmi_input_dev->evbit);
536 set_bit(SW_DOCK, hp_wmi_input_dev->swbit); 453 __set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
537 set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); 454 __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
455
456 err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
457 if (err)
458 goto err_free_dev;
538 459
539 /* Set initial hardware state */ 460 /* Set initial hardware state */
540 input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); 461 input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state());
@@ -542,14 +463,32 @@ static int __init hp_wmi_input_setup(void)
542 hp_wmi_tablet_state()); 463 hp_wmi_tablet_state());
543 input_sync(hp_wmi_input_dev); 464 input_sync(hp_wmi_input_dev);
544 465
545 err = input_register_device(hp_wmi_input_dev); 466 status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
546 467 if (ACPI_FAILURE(status)) {
547 if (err) { 468 err = -EIO;
548 input_free_device(hp_wmi_input_dev); 469 goto err_free_keymap;
549 return err;
550 } 470 }
551 471
472 err = input_register_device(hp_wmi_input_dev);
473 if (err)
474 goto err_uninstall_notifier;
475
552 return 0; 476 return 0;
477
478 err_uninstall_notifier:
479 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
480 err_free_keymap:
481 sparse_keymap_free(hp_wmi_input_dev);
482 err_free_dev:
483 input_free_device(hp_wmi_input_dev);
484 return err;
485}
486
487static void hp_wmi_input_destroy(void)
488{
489 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
490 sparse_keymap_free(hp_wmi_input_dev);
491 input_unregister_device(hp_wmi_input_dev);
553} 492}
554 493
555static void cleanup_sysfs(struct platform_device *device) 494static void cleanup_sysfs(struct platform_device *device)
@@ -704,15 +643,9 @@ static int __init hp_wmi_init(void)
704 int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID); 643 int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
705 644
706 if (event_capable) { 645 if (event_capable) {
707 err = wmi_install_notify_handler(HPWMI_EVENT_GUID,
708 hp_wmi_notify, NULL);
709 if (ACPI_FAILURE(err))
710 return -EINVAL;
711 err = hp_wmi_input_setup(); 646 err = hp_wmi_input_setup();
712 if (err) { 647 if (err)
713 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
714 return err; 648 return err;
715 }
716 } 649 }
717 650
718 if (bios_capable) { 651 if (bios_capable) {
@@ -739,20 +672,17 @@ err_device_add:
739err_device_alloc: 672err_device_alloc:
740 platform_driver_unregister(&hp_wmi_driver); 673 platform_driver_unregister(&hp_wmi_driver);
741err_driver_reg: 674err_driver_reg:
742 if (wmi_has_guid(HPWMI_EVENT_GUID)) { 675 if (event_capable)
743 input_unregister_device(hp_wmi_input_dev); 676 hp_wmi_input_destroy();
744 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
745 }
746 677
747 return err; 678 return err;
748} 679}
749 680
750static void __exit hp_wmi_exit(void) 681static void __exit hp_wmi_exit(void)
751{ 682{
752 if (wmi_has_guid(HPWMI_EVENT_GUID)) { 683 if (wmi_has_guid(HPWMI_EVENT_GUID))
753 wmi_remove_notify_handler(HPWMI_EVENT_GUID); 684 hp_wmi_input_destroy();
754 input_unregister_device(hp_wmi_input_dev); 685
755 }
756 if (hp_wmi_platform_dev) { 686 if (hp_wmi_platform_dev) {
757 platform_device_unregister(hp_wmi_platform_dev); 687 platform_device_unregister(hp_wmi_platform_dev);
758 platform_driver_unregister(&hp_wmi_driver); 688 platform_driver_unregister(&hp_wmi_driver);