summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2010-08-24 12:26:06 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2010-08-24 12:26:06 +1000
commit15d2d559e7398b2552b8b31e19d41690236711a0 (patch)
treee4b64912e10c0471e7bb9c6d3b39532c7a7a19d7
parentd221614a9c4e8e79351e47326408836766610c01 (diff)
parent35989e9d7e19deb4b395aee7d120b1536337b4af (diff)
Merge remote branch 'drivers-x86/linux-next'
-rw-r--r--drivers/platform/x86/Kconfig6
-rw-r--r--drivers/platform/x86/dell-wmi.c256
-rw-r--r--drivers/platform/x86/hp-wmi.c172
-rw-r--r--drivers/platform/x86/panasonic-laptop.c172
-rw-r--r--drivers/platform/x86/topstar-laptop.c161
-rw-r--r--drivers/platform/x86/toshiba_acpi.c191
6 files changed, 331 insertions, 627 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 044f430f3b43..84983898a512 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -92,6 +92,7 @@ config DELL_WMI
tristate "Dell WMI extras"
depends on ACPI_WMI
depends on INPUT
+ select INPUT_SPARSEKMAP
---help---
Say Y here if you want to support WMI-based hotkeys on Dell laptops.
@@ -140,6 +141,7 @@ config HP_WMI
depends on ACPI_WMI
depends on INPUT
depends on RFKILL || RFKILL = n
+ select INPUT_SPARSEKMAP
help
Say Y here if you want to support WMI-based hotkeys on HP laptops and
to read data from WMI such as docking or ambient light sensor state.
@@ -171,6 +173,7 @@ config PANASONIC_LAPTOP
tristate "Panasonic Laptop Extras"
depends on INPUT && ACPI
depends on BACKLIGHT_CLASS_DEVICE
+ select INPUT_SPARSEKMAP
---help---
This driver adds support for access to backlight control and hotkeys
on Panasonic Let's Note laptops.
@@ -478,6 +481,7 @@ config TOPSTAR_LAPTOP
tristate "Topstar Laptop Extras"
depends on ACPI
depends on INPUT
+ select INPUT_SPARSEKMAP
---help---
This driver adds support for hotkeys found on Topstar laptops.
@@ -488,7 +492,7 @@ config ACPI_TOSHIBA
depends on ACPI
depends on INPUT
depends on RFKILL || RFKILL = n
- select INPUT_POLLDEV
+ select INPUT_SPARSEKMAP
select BACKLIGHT_CLASS_DEVICE
---help---
This driver adds support for access to certain system settings
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 08fb70f6d9bf..77f1d55414c6 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
#include <acpi/acpi_drivers.h>
#include <linux/acpi.h>
#include <linux/string.h>
@@ -44,78 +45,70 @@ static int acpi_video;
MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
-struct key_entry {
- char type; /* See KE_* below */
- u16 code;
- u16 keycode;
-};
-
-enum { KE_KEY, KE_SW, KE_IGNORE, KE_END };
-
/*
* Certain keys are flagged as KE_IGNORE. All of these are either
* notifications (rather than requests for change) or are also sent
* via the keyboard controller so should not be sent again.
*/
-static struct key_entry dell_legacy_wmi_keymap[] = {
- {KE_KEY, 0xe045, KEY_PROG1},
- {KE_KEY, 0xe009, KEY_EJECTCD},
+static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
+ { KE_KEY, 0xe045, { KEY_PROG1 } },
+ { KE_KEY, 0xe009, { KEY_EJECTCD } },
/* These also contain the brightness level at offset 6 */
- {KE_KEY, 0xe006, KEY_BRIGHTNESSUP},
- {KE_KEY, 0xe005, KEY_BRIGHTNESSDOWN},
+ { KE_KEY, 0xe006, { KEY_BRIGHTNESSUP } },
+ { KE_KEY, 0xe005, { KEY_BRIGHTNESSDOWN } },
/* Battery health status button */
- {KE_KEY, 0xe007, KEY_BATTERY},
+ { KE_KEY, 0xe007, { KEY_BATTERY } },
/* This is actually for all radios. Although physically a
* switch, the notification does not provide an indication of
* state and so it should be reported as a key */
- {KE_KEY, 0xe008, KEY_WLAN},
+ { KE_KEY, 0xe008, { KEY_WLAN } },
/* The next device is at offset 6, the active devices are at
offset 8 and the attached devices at offset 10 */
- {KE_KEY, 0xe00b, KEY_SWITCHVIDEOMODE},
+ { KE_KEY, 0xe00b, { KEY_SWITCHVIDEOMODE } },
- {KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE},
+ { KE_IGNORE, 0xe00c, { KEY_KBDILLUMTOGGLE } },
/* BIOS error detected */
- {KE_IGNORE, 0xe00d, KEY_RESERVED},
+ { KE_IGNORE, 0xe00d, { KEY_RESERVED } },
/* Wifi Catcher */
- {KE_KEY, 0xe011, KEY_PROG2},
+ { KE_KEY, 0xe011, {KEY_PROG2 } },
/* Ambient light sensor toggle */
- {KE_IGNORE, 0xe013, KEY_RESERVED},
-
- {KE_IGNORE, 0xe020, KEY_MUTE},
- {KE_IGNORE, 0xe02e, KEY_VOLUMEDOWN},
- {KE_IGNORE, 0xe030, KEY_VOLUMEUP},
- {KE_IGNORE, 0xe033, KEY_KBDILLUMUP},
- {KE_IGNORE, 0xe034, KEY_KBDILLUMDOWN},
- {KE_IGNORE, 0xe03a, KEY_CAPSLOCK},
- {KE_IGNORE, 0xe045, KEY_NUMLOCK},
- {KE_IGNORE, 0xe046, KEY_SCROLLLOCK},
- {KE_END, 0}
+ { KE_IGNORE, 0xe013, { KEY_RESERVED } },
+
+ { KE_IGNORE, 0xe020, { KEY_MUTE } },
+ { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } },
+ { KE_IGNORE, 0xe030, { KEY_VOLUMEUP } },
+ { KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } },
+ { KE_IGNORE, 0xe034, { KEY_KBDILLUMDOWN } },
+ { KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } },
+ { KE_IGNORE, 0xe045, { KEY_NUMLOCK } },
+ { KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } },
+ { KE_END, 0 }
};
static bool dell_new_hk_type;
-struct dell_new_keymap_entry {
+struct dell_bios_keymap_entry {
u16 scancode;
u16 keycode;
};
-struct dell_hotkey_table {
+struct dell_bios_hotkey_table {
struct dmi_header header;
- struct dell_new_keymap_entry keymap[];
+ struct dell_bios_keymap_entry keymap[];
};
-static struct key_entry *dell_new_wmi_keymap;
+static const struct dell_bios_hotkey_table *dell_bios_hotkey_table;
-static u16 bios_to_linux_keycode[256] = {
+static const u16 bios_to_linux_keycode[256] __initconst = {
KEY_MEDIA, KEY_NEXTSONG, KEY_PLAYPAUSE, KEY_PREVIOUSSONG,
KEY_STOPCD, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
@@ -138,68 +131,11 @@ static u16 bios_to_linux_keycode[256] = {
KEY_PROG3
};
-
-static struct key_entry *dell_wmi_keymap = dell_legacy_wmi_keymap;
-
static struct input_dev *dell_wmi_input_dev;
-static struct key_entry *dell_wmi_get_entry_by_scancode(unsigned int code)
-{
- struct key_entry *key;
-
- for (key = dell_wmi_keymap; key->type != KE_END; key++)
- if (code == key->code)
- return key;
-
- return NULL;
-}
-
-static struct key_entry *dell_wmi_get_entry_by_keycode(unsigned int keycode)
-{
- struct key_entry *key;
-
- for (key = dell_wmi_keymap; key->type != KE_END; key++)
- if (key->type == KE_KEY && keycode == key->keycode)
- return key;
-
- return NULL;
-}
-
-static int dell_wmi_getkeycode(struct input_dev *dev,
- unsigned int scancode, unsigned int *keycode)
-{
- struct key_entry *key = dell_wmi_get_entry_by_scancode(scancode);
-
- if (key && key->type == KE_KEY) {
- *keycode = key->keycode;
- return 0;
- }
-
- return -EINVAL;
-}
-
-static int dell_wmi_setkeycode(struct input_dev *dev,
- unsigned int scancode, unsigned int keycode)
-{
- struct key_entry *key;
- unsigned int old_keycode;
-
- key = dell_wmi_get_entry_by_scancode(scancode);
- if (key && key->type == KE_KEY) {
- old_keycode = key->keycode;
- key->keycode = keycode;
- set_bit(keycode, dev->keybit);
- if (!dell_wmi_get_entry_by_keycode(old_keycode))
- clear_bit(old_keycode, dev->keybit);
- return 0;
- }
- return -EINVAL;
-}
-
static void dell_wmi_notify(u32 value, void *context)
{
struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
- static struct key_entry *key;
union acpi_object *obj;
acpi_status status;
@@ -212,8 +148,10 @@ static void dell_wmi_notify(u32 value, void *context)
obj = (union acpi_object *)response.pointer;
if (obj && obj->type == ACPI_TYPE_BUFFER) {
+ const struct key_entry *key;
int reported_key;
u16 *buffer_entry = (u16 *)obj->buffer.pointer;
+
if (dell_new_hk_type && (buffer_entry[1] != 0x10)) {
printk(KERN_INFO "dell-wmi: Received unknown WMI event"
" (0x%x)\n", buffer_entry[1]);
@@ -226,8 +164,8 @@ static void dell_wmi_notify(u32 value, void *context)
else
reported_key = (int)buffer_entry[1] & 0xffff;
- key = dell_wmi_get_entry_by_scancode(reported_key);
-
+ key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev,
+ reported_key);
if (!key) {
printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n",
reported_key);
@@ -237,92 +175,98 @@ static void dell_wmi_notify(u32 value, void *context)
* come via ACPI */
;
} else {
- input_report_key(dell_wmi_input_dev, key->keycode, 1);
- input_sync(dell_wmi_input_dev);
- input_report_key(dell_wmi_input_dev, key->keycode, 0);
- input_sync(dell_wmi_input_dev);
+ sparse_keymap_report_entry(dell_wmi_input_dev, key,
+ 1, true);
}
}
kfree(obj);
}
-
-static void setup_new_hk_map(const struct dmi_header *dm)
+static const struct key_entry * __init dell_wmi_prepare_new_keymap(void)
{
-
+ int hotkey_num = (dell_bios_hotkey_table->header.length - 4) /
+ sizeof(struct dell_bios_keymap_entry);
+ struct key_entry *keymap;
int i;
- int hotkey_num = (dm->length-4)/sizeof(struct dell_new_keymap_entry);
- struct dell_hotkey_table *table =
- container_of(dm, struct dell_hotkey_table, header);
- dell_new_wmi_keymap = kzalloc((hotkey_num+1) *
- sizeof(struct key_entry), GFP_KERNEL);
+ keymap = kcalloc(hotkey_num + 1, sizeof(struct key_entry), GFP_KERNEL);
+ if (!keymap)
+ return NULL;
for (i = 0; i < hotkey_num; i++) {
- dell_new_wmi_keymap[i].type = KE_KEY;
- dell_new_wmi_keymap[i].code = table->keymap[i].scancode;
- dell_new_wmi_keymap[i].keycode =
- (table->keymap[i].keycode > 255) ? 0 :
- bios_to_linux_keycode[table->keymap[i].keycode];
+ const struct dell_bios_keymap_entry *bios_entry =
+ &dell_bios_hotkey_table->keymap[i];
+ keymap[i].type = KE_KEY;
+ keymap[i].code = bios_entry->scancode;
+ keymap[i].keycode = bios_entry->keycode < 256 ?
+ bios_to_linux_keycode[bios_entry->keycode] :
+ KEY_RESERVED;
}
- dell_new_wmi_keymap[i].type = KE_END;
- dell_new_wmi_keymap[i].code = 0;
- dell_new_wmi_keymap[i].keycode = 0;
-
- dell_wmi_keymap = dell_new_wmi_keymap;
+ keymap[hotkey_num].type = KE_END;
+ return keymap;
}
-
-static void find_hk_type(const struct dmi_header *dm, void *dummy)
-{
-
- if ((dm->type == 0xb2) && (dm->length > 6)) {
- dell_new_hk_type = true;
- setup_new_hk_map(dm);
- }
-
-}
-
-
static int __init dell_wmi_input_setup(void)
{
- struct key_entry *key;
int err;
dell_wmi_input_dev = input_allocate_device();
-
if (!dell_wmi_input_dev)
return -ENOMEM;
dell_wmi_input_dev->name = "Dell WMI hotkeys";
dell_wmi_input_dev->phys = "wmi/input0";
dell_wmi_input_dev->id.bustype = BUS_HOST;
- dell_wmi_input_dev->getkeycode = dell_wmi_getkeycode;
- dell_wmi_input_dev->setkeycode = dell_wmi_setkeycode;
-
- for (key = dell_wmi_keymap; key->type != KE_END; key++) {
- switch (key->type) {
- case KE_KEY:
- set_bit(EV_KEY, dell_wmi_input_dev->evbit);
- set_bit(key->keycode, dell_wmi_input_dev->keybit);
- break;
- case KE_SW:
- set_bit(EV_SW, dell_wmi_input_dev->evbit);
- set_bit(key->keycode, dell_wmi_input_dev->swbit);
- break;
+
+ if (dell_new_hk_type) {
+ const struct key_entry *keymap = dell_wmi_prepare_new_keymap();
+ if (!keymap) {
+ err = -ENOMEM;
+ goto err_free_dev;
}
- }
- err = input_register_device(dell_wmi_input_dev);
+ err = sparse_keymap_setup(dell_wmi_input_dev, keymap, NULL);
- if (err) {
- input_free_device(dell_wmi_input_dev);
- return err;
+ /*
+ * Sparse keymap library makes a copy of keymap so we
+ * don't need the original one that was allocated.
+ */
+ kfree(keymap);
+ } else {
+ err = sparse_keymap_setup(dell_wmi_input_dev,
+ dell_wmi_legacy_keymap, NULL);
}
+ if (err)
+ goto err_free_dev;
+
+ err = input_register_device(dell_wmi_input_dev);
+ if (err)
+ goto err_free_keymap;
return 0;
+
+ err_free_keymap:
+ sparse_keymap_free(dell_wmi_input_dev);
+ err_free_dev:
+ input_free_device(dell_wmi_input_dev);
+ return err;
+}
+
+static void dell_wmi_input_destroy(void)
+{
+ sparse_keymap_free(dell_wmi_input_dev);
+ input_unregister_device(dell_wmi_input_dev);
+}
+
+static void __init find_hk_type(const struct dmi_header *dm, void *dummy)
+{
+ if (dm->type == 0xb2 && dm->length > 6) {
+ dell_new_hk_type = true;
+ dell_bios_hotkey_table =
+ container_of(dm, struct dell_bios_hotkey_table, header);
+ }
}
static int __init dell_wmi_init(void)
@@ -339,18 +283,13 @@ static int __init dell_wmi_init(void)
acpi_video = acpi_video_backlight_support();
err = dell_wmi_input_setup();
- if (err) {
- if (dell_new_hk_type)
- kfree(dell_wmi_keymap);
+ if (err)
return err;
- }
status = wmi_install_notify_handler(DELL_EVENT_GUID,
dell_wmi_notify, NULL);
if (ACPI_FAILURE(status)) {
- input_unregister_device(dell_wmi_input_dev);
- if (dell_new_hk_type)
- kfree(dell_wmi_keymap);
+ dell_wmi_input_destroy();
printk(KERN_ERR
"dell-wmi: Unable to register notify handler - %d\n",
status);
@@ -359,14 +298,11 @@ static int __init dell_wmi_init(void)
return 0;
}
+module_init(dell_wmi_init);
static void __exit dell_wmi_exit(void)
{
wmi_remove_notify_handler(DELL_EVENT_GUID);
- input_unregister_device(dell_wmi_input_dev);
- if (dell_new_hk_type)
- kfree(dell_wmi_keymap);
+ dell_wmi_input_destroy();
}
-
-module_init(dell_wmi_init);
module_exit(dell_wmi_exit);
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index f15516374987..92a8c1831ca3 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/rfkill.h>
@@ -87,24 +88,16 @@ struct bios_return {
u32 return_code;
};
-struct key_entry {
- char type; /* See KE_* below */
- u16 code;
- u16 keycode;
-};
-
-enum { KE_KEY, KE_END };
-
-static struct key_entry hp_wmi_keymap[] = {
- {KE_KEY, 0x02, KEY_BRIGHTNESSUP},
- {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
- {KE_KEY, 0x20e6, KEY_PROG1},
- {KE_KEY, 0x20e8, KEY_MEDIA},
- {KE_KEY, 0x2142, KEY_MEDIA},
- {KE_KEY, 0x213b, KEY_INFO},
- {KE_KEY, 0x2169, KEY_DIRECTION},
- {KE_KEY, 0x231b, KEY_HELP},
- {KE_END, 0}
+static const struct key_entry hp_wmi_keymap[] = {
+ { KE_KEY, 0x02, { KEY_BRIGHTNESSUP } },
+ { KE_KEY, 0x03, { KEY_BRIGHTNESSDOWN } },
+ { KE_KEY, 0x20e6, { KEY_PROG1 } },
+ { KE_KEY, 0x20e8, { KEY_MEDIA } },
+ { KE_KEY, 0x2142, { KEY_MEDIA } },
+ { KE_KEY, 0x213b, { KEY_INFO } },
+ { KE_KEY, 0x2169, { KEY_DIRECTION } },
+ { KE_KEY, 0x231b, { KEY_HELP } },
+ { KE_END, 0 }
};
static struct input_dev *hp_wmi_input_dev;
@@ -361,64 +354,9 @@ static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als);
static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL);
static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL);
-static struct key_entry *hp_wmi_get_entry_by_scancode(unsigned int code)
-{
- struct key_entry *key;
-
- for (key = hp_wmi_keymap; key->type != KE_END; key++)
- if (code == key->code)
- return key;
-
- return NULL;
-}
-
-static struct key_entry *hp_wmi_get_entry_by_keycode(unsigned int keycode)
-{
- struct key_entry *key;
-
- for (key = hp_wmi_keymap; key->type != KE_END; key++)
- if (key->type == KE_KEY && keycode == key->keycode)
- return key;
-
- return NULL;
-}
-
-static int hp_wmi_getkeycode(struct input_dev *dev,
- unsigned int scancode, unsigned int *keycode)
-{
- struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode);
-
- if (key && key->type == KE_KEY) {
- *keycode = key->keycode;
- return 0;
- }
-
- return -EINVAL;
-}
-
-static int hp_wmi_setkeycode(struct input_dev *dev,
- unsigned int scancode, unsigned int keycode)
-{
- struct key_entry *key;
- unsigned int old_keycode;
-
- key = hp_wmi_get_entry_by_scancode(scancode);
- if (key && key->type == KE_KEY) {
- old_keycode = key->keycode;
- key->keycode = keycode;
- set_bit(keycode, dev->keybit);
- if (!hp_wmi_get_entry_by_keycode(old_keycode))
- clear_bit(old_keycode, dev->keybit);
- return 0;
- }
-
- return -EINVAL;
-}
-
static void hp_wmi_notify(u32 value, void *context)
{
struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
- static struct key_entry *key;
union acpi_object *obj;
u32 event_id, event_data;
int key_code, ret;
@@ -479,19 +417,9 @@ static void hp_wmi_notify(u32 value, void *context)
sizeof(key_code));
if (ret)
break;
- key = hp_wmi_get_entry_by_scancode(key_code);
- if (key) {
- switch (key->type) {
- case KE_KEY:
- input_report_key(hp_wmi_input_dev,
- key->keycode, 1);
- input_sync(hp_wmi_input_dev);
- input_report_key(hp_wmi_input_dev,
- key->keycode, 0);
- input_sync(hp_wmi_input_dev);
- break;
- }
- } else
+
+ if (!sparse_keymap_report_event(hp_wmi_input_dev,
+ key_code, 1, true))
printk(KERN_INFO PREFIX "Unknown key code - 0x%x\n",
key_code);
break;
@@ -524,7 +452,7 @@ static void hp_wmi_notify(u32 value, void *context)
static int __init hp_wmi_input_setup(void)
{
- struct key_entry *key;
+ acpi_status status;
int err;
hp_wmi_input_dev = input_allocate_device();
@@ -534,21 +462,14 @@ static int __init hp_wmi_input_setup(void)
hp_wmi_input_dev->name = "HP WMI hotkeys";
hp_wmi_input_dev->phys = "wmi/input0";
hp_wmi_input_dev->id.bustype = BUS_HOST;
- hp_wmi_input_dev->getkeycode = hp_wmi_getkeycode;
- hp_wmi_input_dev->setkeycode = hp_wmi_setkeycode;
-
- for (key = hp_wmi_keymap; key->type != KE_END; key++) {
- switch (key->type) {
- case KE_KEY:
- set_bit(EV_KEY, hp_wmi_input_dev->evbit);
- set_bit(key->keycode, hp_wmi_input_dev->keybit);
- break;
- }
- }
- set_bit(EV_SW, hp_wmi_input_dev->evbit);
- set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
- set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
+ __set_bit(EV_SW, hp_wmi_input_dev->evbit);
+ __set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
+ __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
+
+ err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
+ if (err)
+ goto err_free_dev;
/* Set initial hardware state */
input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state());
@@ -556,14 +477,32 @@ static int __init hp_wmi_input_setup(void)
hp_wmi_tablet_state());
input_sync(hp_wmi_input_dev);
- err = input_register_device(hp_wmi_input_dev);
-
- if (err) {
- input_free_device(hp_wmi_input_dev);
- return err;
+ status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
+ if (ACPI_FAILURE(status)) {
+ err = -EIO;
+ goto err_free_keymap;
}
+ err = input_register_device(hp_wmi_input_dev);
+ if (err)
+ goto err_uninstall_notifier;
+
return 0;
+
+ err_uninstall_notifier:
+ wmi_remove_notify_handler(HPWMI_EVENT_GUID);
+ err_free_keymap:
+ sparse_keymap_free(hp_wmi_input_dev);
+ err_free_dev:
+ input_free_device(hp_wmi_input_dev);
+ return err;
+}
+
+static void hp_wmi_input_destroy(void)
+{
+ wmi_remove_notify_handler(HPWMI_EVENT_GUID);
+ sparse_keymap_free(hp_wmi_input_dev);
+ input_unregister_device(hp_wmi_input_dev);
}
static void cleanup_sysfs(struct platform_device *device)
@@ -718,15 +657,9 @@ static int __init hp_wmi_init(void)
int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
if (event_capable) {
- err = wmi_install_notify_handler(HPWMI_EVENT_GUID,
- hp_wmi_notify, NULL);
- if (ACPI_FAILURE(err))
- return -EINVAL;
err = hp_wmi_input_setup();
- if (err) {
- wmi_remove_notify_handler(HPWMI_EVENT_GUID);
+ if (err)
return err;
- }
}
if (bios_capable) {
@@ -753,20 +686,17 @@ err_device_add:
err_device_alloc:
platform_driver_unregister(&hp_wmi_driver);
err_driver_reg:
- if (wmi_has_guid(HPWMI_EVENT_GUID)) {
- input_unregister_device(hp_wmi_input_dev);
- wmi_remove_notify_handler(HPWMI_EVENT_GUID);
- }
+ if (event_capable)
+ hp_wmi_input_destroy();
return err;
}
static void __exit hp_wmi_exit(void)
{
- if (wmi_has_guid(HPWMI_EVENT_GUID)) {
- wmi_remove_notify_handler(HPWMI_EVENT_GUID);
- input_unregister_device(hp_wmi_input_dev);
- }
+ if (wmi_has_guid(HPWMI_EVENT_GUID))
+ hp_wmi_input_destroy();
+
if (hp_wmi_platform_dev) {
platform_device_unregister(hp_wmi_platform_dev);
platform_driver_unregister(&hp_wmi_driver);
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index ec01c3d8fc5a..b3b9e0458ae1 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -128,6 +128,7 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
#ifndef ACPI_HOTKEY_COMPONENT
@@ -200,30 +201,29 @@ static struct acpi_driver acpi_pcc_driver = {
},
};
-#define KEYMAP_SIZE 11
-static const unsigned int initial_keymap[KEYMAP_SIZE] = {
- /* 0 */ KEY_RESERVED,
- /* 1 */ KEY_BRIGHTNESSDOWN,
- /* 2 */ KEY_BRIGHTNESSUP,
- /* 3 */ KEY_DISPLAYTOGGLE,
- /* 4 */ KEY_MUTE,
- /* 5 */ KEY_VOLUMEDOWN,
- /* 6 */ KEY_VOLUMEUP,
- /* 7 */ KEY_SLEEP,
- /* 8 */ KEY_PROG1, /* Change CPU boost */
- /* 9 */ KEY_BATTERY,
- /* 10 */ KEY_SUSPEND,
+static const struct key_entry panasonic_keymap[] = {
+ { KE_KEY, 0, { KEY_RESERVED } },
+ { KE_KEY, 1, { KEY_BRIGHTNESSDOWN } },
+ { KE_KEY, 2, { KEY_BRIGHTNESSUP } },
+ { KE_KEY, 3, { KEY_DISPLAYTOGGLE } },
+ { KE_KEY, 4, { KEY_MUTE } },
+ { KE_KEY, 5, { KEY_VOLUMEDOWN } },
+ { KE_KEY, 6, { KEY_VOLUMEUP } },
+ { KE_KEY, 7, { KEY_SLEEP } },
+ { KE_KEY, 8, { KEY_PROG1 } }, /* Change CPU boost */
+ { KE_KEY, 9, { KEY_BATTERY } },
+ { KE_KEY, 10, { KEY_SUSPEND } },
+ { KE_END, 0 }
};
struct pcc_acpi {
acpi_handle handle;
unsigned long num_sifr;
int sticky_mode;
- u32 *sinf;
+ u32 *sinf;
struct acpi_device *device;
struct input_dev *input_dev;
struct backlight_device *backlight;
- unsigned int keymap[KEYMAP_SIZE];
};
struct pcc_keyinput {
@@ -446,56 +446,10 @@ static struct attribute_group pcc_attr_group = {
/* hotkey input device driver */
-static int pcc_getkeycode(struct input_dev *dev,
- unsigned int scancode, unsigned int *keycode)
-{
- struct pcc_acpi *pcc = input_get_drvdata(dev);
-
- if (scancode >= ARRAY_SIZE(pcc->keymap))
- return -EINVAL;
-
- *keycode = pcc->keymap[scancode];
-
- return 0;
-}
-
-static int keymap_get_by_keycode(struct pcc_acpi *pcc, unsigned int keycode)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) {
- if (pcc->keymap[i] == keycode)
- return i+1;
- }
-
- return 0;
-}
-
-static int pcc_setkeycode(struct input_dev *dev,
- unsigned int scancode, unsigned int keycode)
-{
- struct pcc_acpi *pcc = input_get_drvdata(dev);
- int oldkeycode;
-
- if (scancode >= ARRAY_SIZE(pcc->keymap))
- return -EINVAL;
-
- oldkeycode = pcc->keymap[scancode];
- pcc->keymap[scancode] = keycode;
-
- set_bit(keycode, dev->keybit);
-
- if (!keymap_get_by_keycode(pcc, oldkeycode))
- clear_bit(oldkeycode, dev->keybit);
-
- return 0;
-}
-
static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
{
struct input_dev *hotk_input_dev = pcc->input_dev;
int rc;
- int key_code, hkey_num;
unsigned long long result;
rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
@@ -508,25 +462,10 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result);
- hkey_num = result & 0xf;
-
- if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) {
+ if (!sparse_keymap_report_event(hotk_input_dev,
+ result & 0xf, result & 0x80, false))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "hotkey number out of range: %d\n",
- hkey_num));
- return;
- }
-
- key_code = pcc->keymap[hkey_num];
-
- if (key_code != KEY_RESERVED) {
- int pushed = (result & 0x80) ? TRUE : FALSE;
-
- input_report_key(hotk_input_dev, key_code, pushed);
- input_sync(hotk_input_dev);
- }
-
- return;
+ "Unknown hotkey event: %d\n", result));
}
static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
@@ -545,40 +484,55 @@ static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
static int acpi_pcc_init_input(struct pcc_acpi *pcc)
{
- int i, rc;
+ struct input_dev *input_dev;
+ int error;
- pcc->input_dev = input_allocate_device();
- if (!pcc->input_dev) {
+ input_dev = input_allocate_device();
+ if (!input_dev) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Couldn't allocate input device for hotkey"));
return -ENOMEM;
}
- pcc->input_dev->evbit[0] = BIT(EV_KEY);
-
- pcc->input_dev->name = ACPI_PCC_DRIVER_NAME;
- pcc->input_dev->phys = ACPI_PCC_INPUT_PHYS;
- pcc->input_dev->id.bustype = BUS_HOST;
- pcc->input_dev->id.vendor = 0x0001;
- pcc->input_dev->id.product = 0x0001;
- pcc->input_dev->id.version = 0x0100;
- pcc->input_dev->getkeycode = pcc_getkeycode;
- pcc->input_dev->setkeycode = pcc_setkeycode;
+ input_dev->name = ACPI_PCC_DRIVER_NAME;
+ input_dev->phys = ACPI_PCC_INPUT_PHYS;
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
- /* load initial keymap */
- memcpy(pcc->keymap, initial_keymap, sizeof(pcc->keymap));
+ error = sparse_keymap_setup(input_dev, panasonic_keymap, NULL);
+ if (error) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to setup input device keymap\n"));
+ goto err_free_dev;
+ }
- for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++)
- __set_bit(pcc->keymap[i], pcc->input_dev->keybit);
- __clear_bit(KEY_RESERVED, pcc->input_dev->keybit);
+ error = input_register_device(input_dev);
+ if (error) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to register input device\n"));
+ goto err_free_keymap;
+ }
- input_set_drvdata(pcc->input_dev, pcc);
+ pcc->input_dev = input_dev;
+ return 0;
- rc = input_register_device(pcc->input_dev);
- if (rc < 0)
- input_free_device(pcc->input_dev);
+ err_free_keymap:
+ sparse_keymap_free(input_dev);
+ err_free_dev:
+ input_free_device(input_dev);
+ return error;
+}
- return rc;
+static void acpi_pcc_destroy_input(struct pcc_acpi *pcc)
+{
+ sparse_keymap_free(pcc->input_dev);
+ input_unregister_device(pcc->input_dev);
+ /*
+ * No need to input_free_device() since core input API refcounts
+ * and free()s the device.
+ */
}
/* kernel module interface */
@@ -636,7 +590,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error installing keyinput handler\n"));
- goto out_hotkey;
+ goto out_sinf;
}
if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) {
@@ -651,7 +605,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
&pcc_backlight_ops, &props);
if (IS_ERR(pcc->backlight)) {
result = PTR_ERR(pcc->backlight);
- goto out_sinf;
+ goto out_input;
}
/* read the initial brightness setting from the hardware */
@@ -669,12 +623,10 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
out_backlight:
backlight_device_unregister(pcc->backlight);
+out_input:
+ acpi_pcc_destroy_input(pcc);
out_sinf:
kfree(pcc->sinf);
-out_input:
- input_unregister_device(pcc->input_dev);
- /* no need to input_free_device() since core input API refcount and
- * free()s the device */
out_hotkey:
kfree(pcc);
@@ -709,9 +661,7 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
backlight_device_unregister(pcc->backlight);
- input_unregister_device(pcc->input_dev);
- /* no need to input_free_device() since core input API refcount and
- * free()s the device */
+ acpi_pcc_destroy_input(pcc);
kfree(pcc->sinf);
kfree(pcc);
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index ff4b476f1950..1d07d6d09f27 100644
--- a/drivers/platform/x86/topstar-laptop.c
+++ b/drivers/platform/x86/topstar-laptop.c
@@ -19,6 +19,7 @@
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
#define ACPI_TOPSTAR_CLASS "topstar"
@@ -26,52 +27,37 @@ struct topstar_hkey {
struct input_dev *inputdev;
};
-struct tps_key_entry {
- u8 code;
- u16 keycode;
-};
-
-static struct tps_key_entry topstar_keymap[] = {
- { 0x80, KEY_BRIGHTNESSUP },
- { 0x81, KEY_BRIGHTNESSDOWN },
- { 0x83, KEY_VOLUMEUP },
- { 0x84, KEY_VOLUMEDOWN },
- { 0x85, KEY_MUTE },
- { 0x86, KEY_SWITCHVIDEOMODE },
- { 0x87, KEY_F13 }, /* touchpad enable/disable key */
- { 0x88, KEY_WLAN },
- { 0x8a, KEY_WWW },
- { 0x8b, KEY_MAIL },
- { 0x8c, KEY_MEDIA },
- { 0x96, KEY_F14 }, /* G key? */
- { }
-};
-
-static struct tps_key_entry *tps_get_key_by_scancode(unsigned int code)
-{
- struct tps_key_entry *key;
-
- for (key = topstar_keymap; key->code; key++)
- if (code == key->code)
- return key;
+static const struct key_entry topstar_keymap[] = {
+ { KE_KEY, 0x80, { KEY_BRIGHTNESSUP } },
+ { KE_KEY, 0x81, { KEY_BRIGHTNESSDOWN } },
+ { KE_KEY, 0x83, { KEY_VOLUMEUP } },
+ { KE_KEY, 0x84, { KEY_VOLUMEDOWN } },
+ { KE_KEY, 0x85, { KEY_MUTE } },
+ { KE_KEY, 0x86, { KEY_SWITCHVIDEOMODE } },
+ { KE_KEY, 0x87, { KEY_F13 } }, /* touchpad enable/disable key */
+ { KE_KEY, 0x88, { KEY_WLAN } },
+ { KE_KEY, 0x8a, { KEY_WWW } },
+ { KE_KEY, 0x8b, { KEY_MAIL } },
+ { KE_KEY, 0x8c, { KEY_MEDIA } },
- return NULL;
-}
-
-static struct tps_key_entry *tps_get_key_by_keycode(unsigned int code)
-{
- struct tps_key_entry *key;
+ /* Known non hotkey events don't handled or that we don't care yet */
+ { KE_IGNORE, 0x8e, },
+ { KE_IGNORE, 0x8f, },
+ { KE_IGNORE, 0x90, },
- for (key = topstar_keymap; key->code; key++)
- if (code == key->keycode)
- return key;
+ /*
+ * 'G key' generate two event codes, convert to only
+ * one event/key code for now, consider replacing by
+ * a switch (3G switch - SW_3G?)
+ */
+ { KE_KEY, 0x96, { KEY_F14 } },
+ { KE_KEY, 0x97, { KEY_F14 } },
- return NULL;
-}
+ { KE_END, 0 }
+};
static void acpi_topstar_notify(struct acpi_device *device, u32 event)
{
- struct tps_key_entry *key;
static bool dup_evnt[2];
bool *dup;
struct topstar_hkey *hkey = acpi_driver_data(device);
@@ -86,27 +72,8 @@ static void acpi_topstar_notify(struct acpi_device *device, u32 event)
*dup = true;
}
- /*
- * 'G key' generate two event codes, convert to only
- * one event/key code for now (3G switch?)
- */
- if (event == 0x97)
- event = 0x96;
-
- key = tps_get_key_by_scancode(event);
- if (key) {
- input_report_key(hkey->inputdev, key->keycode, 1);
- input_sync(hkey->inputdev);
- input_report_key(hkey->inputdev, key->keycode, 0);
- input_sync(hkey->inputdev);
- return;
- }
-
- /* Known non hotkey events don't handled or that we don't care yet */
- if (event == 0x8e || event == 0x8f || event == 0x90)
- return;
-
- pr_info("unknown event = 0x%02x\n", event);
+ if (!sparse_keymap_report_event(hkey->inputdev, event, 1, true))
+ pr_info("unknown event = 0x%02x\n", event);
}
static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
@@ -127,62 +94,41 @@ static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
return 0;
}
-static int topstar_getkeycode(struct input_dev *dev,
- unsigned int scancode, unsigned int *keycode)
-{
- struct tps_key_entry *key = tps_get_key_by_scancode(scancode);
-
- if (!key)
- return -EINVAL;
-
- *keycode = key->keycode;
- return 0;
-}
-
-static int topstar_setkeycode(struct input_dev *dev,
- unsigned int scancode, unsigned int keycode)
-{
- struct tps_key_entry *key;
- int old_keycode;
-
- key = tps_get_key_by_scancode(scancode);
-
- if (!key)
- return -EINVAL;
-
- old_keycode = key->keycode;
- key->keycode = keycode;
- set_bit(keycode, dev->keybit);
- if (!tps_get_key_by_keycode(old_keycode))
- clear_bit(old_keycode, dev->keybit);
- return 0;
-}
-
static int acpi_topstar_init_hkey(struct topstar_hkey *hkey)
{
- struct tps_key_entry *key;
+ struct input_dev *input;
+ int error;
- hkey->inputdev = input_allocate_device();
- if (!hkey->inputdev) {
+ input = input_allocate_device();
+ if (!input) {
pr_err("Unable to allocate input device\n");
- return -ENODEV;
+ return -ENOMEM;
}
- hkey->inputdev->name = "Topstar Laptop extra buttons";
- hkey->inputdev->phys = "topstar/input0";
- hkey->inputdev->id.bustype = BUS_HOST;
- hkey->inputdev->getkeycode = topstar_getkeycode;
- hkey->inputdev->setkeycode = topstar_setkeycode;
- for (key = topstar_keymap; key->code; key++) {
- set_bit(EV_KEY, hkey->inputdev->evbit);
- set_bit(key->keycode, hkey->inputdev->keybit);
+
+ input->name = "Topstar Laptop extra buttons";
+ input->phys = "topstar/input0";
+ input->id.bustype = BUS_HOST;
+
+ error = sparse_keymap_setup(input, topstar_keymap, NULL);
+ if (error) {
+ pr_err("Unable to setup input device keymap\n");
+ goto err_free_dev;
}
- if (input_register_device(hkey->inputdev)) {
+
+ error = input_register_device(input);
+ if (error) {
pr_err("Unable to register input device\n");
- input_free_device(hkey->inputdev);
- return -ENODEV;
+ goto err_free_keymap;
}
+ hkey->inputdev = input;
return 0;
+
+ err_free_keymap:
+ sparse_keymap_free(input);
+ err_free_dev:
+ input_free_device(input);
+ return error;
}
static int acpi_topstar_add(struct acpi_device *device)
@@ -216,6 +162,7 @@ static int acpi_topstar_remove(struct acpi_device *device, int type)
acpi_topstar_fncx_switch(device, false);
+ sparse_keymap_free(tps_hkey->inputdev);
input_unregister_device(tps_hkey->inputdev);
kfree(tps_hkey);
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 7d67a45bb2b0..06f304f46e02 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -48,6 +48,7 @@
#include <linux/platform_device.h>
#include <linux/rfkill.h>
#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
#include <linux/leds.h>
#include <linux/slab.h>
@@ -121,36 +122,28 @@ static const struct acpi_device_id toshiba_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
-struct key_entry {
- char type;
- u16 code;
- u16 keycode;
-};
-
-enum {KE_KEY, KE_END};
-
-static struct key_entry toshiba_acpi_keymap[] = {
- {KE_KEY, 0x101, KEY_MUTE},
- {KE_KEY, 0x102, KEY_ZOOMOUT},
- {KE_KEY, 0x103, KEY_ZOOMIN},
- {KE_KEY, 0x13b, KEY_COFFEE},
- {KE_KEY, 0x13c, KEY_BATTERY},
- {KE_KEY, 0x13d, KEY_SLEEP},
- {KE_KEY, 0x13e, KEY_SUSPEND},
- {KE_KEY, 0x13f, KEY_SWITCHVIDEOMODE},
- {KE_KEY, 0x140, KEY_BRIGHTNESSDOWN},
- {KE_KEY, 0x141, KEY_BRIGHTNESSUP},
- {KE_KEY, 0x142, KEY_WLAN},
- {KE_KEY, 0x143, KEY_PROG1},
- {KE_KEY, 0xb05, KEY_PROG2},
- {KE_KEY, 0xb06, KEY_WWW},
- {KE_KEY, 0xb07, KEY_MAIL},
- {KE_KEY, 0xb30, KEY_STOP},
- {KE_KEY, 0xb31, KEY_PREVIOUSSONG},
- {KE_KEY, 0xb32, KEY_NEXTSONG},
- {KE_KEY, 0xb33, KEY_PLAYPAUSE},
- {KE_KEY, 0xb5a, KEY_MEDIA},
- {KE_END, 0, 0},
+static const struct key_entry toshiba_acpi_keymap[] __initconst = {
+ { KE_KEY, 0x101, { KEY_MUTE } },
+ { KE_KEY, 0x102, { KEY_ZOOMOUT } },
+ { KE_KEY, 0x103, { KEY_ZOOMIN } },
+ { KE_KEY, 0x13b, { KEY_COFFEE } },
+ { KE_KEY, 0x13c, { KEY_BATTERY } },
+ { KE_KEY, 0x13d, { KEY_SLEEP } },
+ { KE_KEY, 0x13e, { KEY_SUSPEND } },
+ { KE_KEY, 0x13f, { KEY_SWITCHVIDEOMODE } },
+ { KE_KEY, 0x140, { KEY_BRIGHTNESSDOWN } },
+ { KE_KEY, 0x141, { KEY_BRIGHTNESSUP } },
+ { KE_KEY, 0x142, { KEY_WLAN } },
+ { KE_KEY, 0x143, { KEY_PROG1 } },
+ { KE_KEY, 0xb05, { KEY_PROG2 } },
+ { KE_KEY, 0xb06, { KEY_WWW } },
+ { KE_KEY, 0xb07, { KEY_MAIL } },
+ { KE_KEY, 0xb30, { KEY_STOP } },
+ { KE_KEY, 0xb31, { KEY_PREVIOUSSONG } },
+ { KE_KEY, 0xb32, { KEY_NEXTSONG } },
+ { KE_KEY, 0xb33, { KEY_PLAYPAUSE } },
+ { KE_KEY, 0xb5a, { KEY_MEDIA } },
+ { KE_END, 0 },
};
/* utility
@@ -852,64 +845,9 @@ static struct backlight_ops toshiba_backlight_data = {
.update_status = set_lcd_status,
};
-static struct key_entry *toshiba_acpi_get_entry_by_scancode(unsigned int code)
-{
- struct key_entry *key;
-
- for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
- if (code == key->code)
- return key;
-
- return NULL;
-}
-
-static struct key_entry *toshiba_acpi_get_entry_by_keycode(unsigned int code)
-{
- struct key_entry *key;
-
- for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
- if (code == key->keycode && key->type == KE_KEY)
- return key;
-
- return NULL;
-}
-
-static int toshiba_acpi_getkeycode(struct input_dev *dev,
- unsigned int scancode, unsigned int *keycode)
-{
- struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode);
-
- if (key && key->type == KE_KEY) {
- *keycode = key->keycode;
- return 0;
- }
-
- return -EINVAL;
-}
-
-static int toshiba_acpi_setkeycode(struct input_dev *dev,
- unsigned int scancode, unsigned int keycode)
-{
- struct key_entry *key;
- unsigned int old_keycode;
-
- key = toshiba_acpi_get_entry_by_scancode(scancode);
- if (key && key->type == KE_KEY) {
- old_keycode = key->keycode;
- key->keycode = keycode;
- set_bit(keycode, dev->keybit);
- if (!toshiba_acpi_get_entry_by_keycode(old_keycode))
- clear_bit(old_keycode, dev->keybit);
- return 0;
- }
-
- return -EINVAL;
-}
-
static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
{
u32 hci_result, value;
- struct key_entry *key;
if (event != 0x80)
return;
@@ -922,19 +860,11 @@ static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
if (value & 0x80)
continue;
- key = toshiba_acpi_get_entry_by_scancode
- (value);
- if (!key) {
+ if (!sparse_keymap_report_event(toshiba_acpi.hotkey_dev,
+ value, 1, true)) {
printk(MY_INFO "Unknown key %x\n",
value);
- continue;
}
- input_report_key(toshiba_acpi.hotkey_dev,
- key->keycode, 1);
- input_sync(toshiba_acpi.hotkey_dev);
- input_report_key(toshiba_acpi.hotkey_dev,
- key->keycode, 0);
- input_sync(toshiba_acpi.hotkey_dev);
} else if (hci_result == HCI_NOT_SUPPORTED) {
/* This is a workaround for an unresolved issue on
* some machines where system events sporadically
@@ -945,34 +875,17 @@ static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
} while (hci_result != HCI_EMPTY);
}
-static int toshiba_acpi_setup_keyboard(char *device)
+static int __init toshiba_acpi_setup_keyboard(char *device)
{
acpi_status status;
- acpi_handle handle;
- int result;
- const struct key_entry *key;
+ int error;
- status = acpi_get_handle(NULL, device, &handle);
+ status = acpi_get_handle(NULL, device, &toshiba_acpi.handle);
if (ACPI_FAILURE(status)) {
printk(MY_INFO "Unable to get notification device\n");
return -ENODEV;
}
- toshiba_acpi.handle = handle;
-
- status = acpi_evaluate_object(handle, "ENAB", NULL, NULL);
- if (ACPI_FAILURE(status)) {
- printk(MY_INFO "Unable to enable hotkeys\n");
- return -ENODEV;
- }
-
- status = acpi_install_notify_handler(handle, ACPI_DEVICE_NOTIFY,
- toshiba_acpi_notify, NULL);
- if (ACPI_FAILURE(status)) {
- printk(MY_INFO "Unable to install hotkey notification\n");
- return -ENODEV;
- }
-
toshiba_acpi.hotkey_dev = input_allocate_device();
if (!toshiba_acpi.hotkey_dev) {
printk(MY_INFO "Unable to register input device\n");
@@ -982,27 +895,54 @@ static int toshiba_acpi_setup_keyboard(char *device)
toshiba_acpi.hotkey_dev->name = "Toshiba input device";
toshiba_acpi.hotkey_dev->phys = device;
toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST;
- toshiba_acpi.hotkey_dev->getkeycode = toshiba_acpi_getkeycode;
- toshiba_acpi.hotkey_dev->setkeycode = toshiba_acpi_setkeycode;
- for (key = toshiba_acpi_keymap; key->type != KE_END; key++) {
- set_bit(EV_KEY, toshiba_acpi.hotkey_dev->evbit);
- set_bit(key->keycode, toshiba_acpi.hotkey_dev->keybit);
+ error = sparse_keymap_setup(toshiba_acpi.hotkey_dev,
+ toshiba_acpi_keymap, NULL);
+ if (error)
+ goto err_free_dev;
+
+ status = acpi_install_notify_handler(toshiba_acpi.handle,
+ ACPI_DEVICE_NOTIFY, toshiba_acpi_notify, NULL);
+ if (ACPI_FAILURE(status)) {
+ printk(MY_INFO "Unable to install hotkey notification\n");
+ error = -ENODEV;
+ goto err_free_keymap;
+ }
+
+ status = acpi_evaluate_object(toshiba_acpi.handle, "ENAB", NULL, NULL);
+ if (ACPI_FAILURE(status)) {
+ printk(MY_INFO "Unable to enable hotkeys\n");
+ error = -ENODEV;
+ goto err_remove_notify;
}
- result = input_register_device(toshiba_acpi.hotkey_dev);
- if (result) {
+ error = input_register_device(toshiba_acpi.hotkey_dev);
+ if (error) {
printk(MY_INFO "Unable to register input device\n");
- return result;
+ goto err_remove_notify;
}
return 0;
+
+ err_remove_notify:
+ acpi_remove_notify_handler(toshiba_acpi.handle,
+ ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
+ err_free_keymap:
+ sparse_keymap_free(toshiba_acpi.hotkey_dev);
+ err_free_dev:
+ input_free_device(toshiba_acpi.hotkey_dev);
+ toshiba_acpi.hotkey_dev = NULL;
+ return error;
}
static void toshiba_acpi_exit(void)
{
- if (toshiba_acpi.hotkey_dev)
+ if (toshiba_acpi.hotkey_dev) {
+ acpi_remove_notify_handler(toshiba_acpi.handle,
+ ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
+ sparse_keymap_free(toshiba_acpi.hotkey_dev);
input_unregister_device(toshiba_acpi.hotkey_dev);
+ }
if (toshiba_acpi.bt_rfk) {
rfkill_unregister(toshiba_acpi.bt_rfk);
@@ -1017,9 +957,6 @@ static void toshiba_acpi_exit(void)
if (toshiba_proc_dir)
remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
- acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY,
- toshiba_acpi_notify);
-
if (toshiba_acpi.illumination_installed)
led_classdev_unregister(&toshiba_led);