Message ID | 1294764176-9760-3-git-send-email-colin.king@canonical.com |
---|---|
State | Accepted |
Delegated to: | Brad Figg |
Headers | show |
On 01/11/2011 10:42 AM, Colin King wrote: > From: Colin Ian King<colin.king@canonical.com> > > The original implementaion failed to use spare keymaps which resulted > in quite a bit of unwanted bloat. Use spare keymaps and tidy up the > code. > > BugLink: http://bugs.launchpad.net/bugs/701530 > > Signed-off-by: Colin Ian King<colin.king@canonical.com> > --- > drivers/platform/x86/dell-wmi-aio.c | 132 ++++++----------------------------- > 1 files changed, 22 insertions(+), 110 deletions(-) > > diff --git a/drivers/platform/x86/dell-wmi-aio.c b/drivers/platform/x86/dell-wmi-aio.c > index e770cb3..755c6d2 100644 > --- a/drivers/platform/x86/dell-wmi-aio.c > +++ b/drivers/platform/x86/dell-wmi-aio.c > @@ -21,6 +21,7 @@ > #include<linux/init.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> > @@ -46,99 +47,14 @@ MODULE_ALIAS("dmi:*:*Dell*:*:"); > MODULE_ALIAS("wmi:"EVENT_GUID1); > MODULE_ALIAS("wmi:"EVENT_GUID2); > > -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_wmi_aio_keymap[] = { > - { KE_KEY, 0xc0, KEY_VOLUMEUP }, > - { KE_KEY, 0xc1, KEY_VOLUMEDOWN }, > + { KE_KEY, 0xc0, { KEY_VOLUMEUP } }, > + { KE_KEY, 0xc1, { KEY_VOLUMEDOWN } }, > { KE_END, 0 } > }; > > static struct input_dev *dell_wmi_aio_input_dev; > > -static struct key_entry *dell_wmi_aio_get_entry_by_scancode(int code) > -{ > - struct key_entry *key; > - > - for (key = dell_wmi_aio_keymap; key->type != KE_END; key++) > - if (code == key->code) > - return key; > - > - return NULL; > -} > - > -static struct key_entry *dell_wmi_aio_get_entry_by_keycode(int keycode) > -{ > - struct key_entry *key; > - > - for (key = dell_wmi_aio_keymap; key->type != KE_END; key++) > - if (key->type == KE_KEY&& keycode == key->keycode) > - return key; > - > - return NULL; > -} > - > -static int dell_wmi_aio_getkeycode(struct input_dev *dev, int scancode, > - int *keycode) > -{ > - struct key_entry *key = dell_wmi_aio_get_entry_by_scancode(scancode); > - > - if (key&& key->type == KE_KEY) { > - *keycode = key->keycode; > - return 0; > - } > - > - return -EINVAL; > -} > - > -static int dell_wmi_aio_setkeycode(struct input_dev *dev, int scancode, > - int keycode) > -{ > - struct key_entry *key; > - int old_keycode; > - > - if (keycode< 0 || keycode> KEY_MAX) > - return -EINVAL; > - > - key = dell_wmi_aio_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_aio_get_entry_by_keycode(old_keycode)) > - clear_bit(old_keycode, dev->keybit); > - return 0; > - } > - return -EINVAL; > -} > - > -static void dell_wmi_aio_handle_key(unsigned int scancode) > -{ > - static struct key_entry *key; > - > - key = dell_wmi_aio_get_entry_by_scancode(scancode); > - if (key) { > - input_report_key(dell_wmi_aio_input_dev, key->keycode, 1); > - input_sync(dell_wmi_aio_input_dev); > - input_report_key(dell_wmi_aio_input_dev, key->keycode, 0); > - input_sync(dell_wmi_aio_input_dev); > - } else if (scancode) > - pr_info(AIO_PREFIX "Unknown key %x pressed\n", > - scancode); > -} > - > static void dell_wmi_aio_notify(u32 value, void *context) > { > struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; > @@ -159,13 +75,16 @@ static void dell_wmi_aio_notify(u32 value, void *context) > case ACPI_TYPE_INTEGER: > /* Most All-In-One correctly return integer scancode */ > scancode = obj->integer.value; > - dell_wmi_aio_handle_key(scancode); > + sparse_keymap_report_event(dell_wmi_aio_input_dev, > + scancode, 1, true); > break; > case ACPI_TYPE_BUFFER: > /* Broken machines return the scancode in a buffer */ > if (obj->buffer.pointer&& obj->buffer.length> 0) { > scancode = obj->buffer.pointer[0]; > - dell_wmi_aio_handle_key(scancode); > + sparse_keymap_report_event( > + dell_wmi_aio_input_dev, > + scancode, 1, true); > } > break; > } > @@ -175,7 +94,6 @@ static void dell_wmi_aio_notify(u32 value, void *context) > > static int __init dell_wmi_aio_input_setup(void) > { > - struct key_entry *key; > int err; > > dell_wmi_aio_input_dev = input_allocate_device(); > @@ -186,30 +104,25 @@ static int __init dell_wmi_aio_input_setup(void) > dell_wmi_aio_input_dev->name = "Dell AIO WMI hotkeys"; > dell_wmi_aio_input_dev->phys = "wmi/input0"; > dell_wmi_aio_input_dev->id.bustype = BUS_HOST; > - dell_wmi_aio_input_dev->getkeycode = dell_wmi_aio_getkeycode; > - dell_wmi_aio_input_dev->setkeycode = dell_wmi_aio_setkeycode; > > - for (key = dell_wmi_aio_keymap; key->type != KE_END; key++) { > - switch (key->type) { > - case KE_KEY: > - set_bit(EV_KEY, dell_wmi_aio_input_dev->evbit); > - set_bit(key->keycode, dell_wmi_aio_input_dev->keybit); > - break; > - case KE_SW: > - set_bit(EV_SW, dell_wmi_aio_input_dev->evbit); > - set_bit(key->keycode, dell_wmi_aio_input_dev->swbit); > - break; > - } > + err = sparse_keymap_setup(dell_wmi_aio_input_dev, > + dell_wmi_aio_keymap, NULL); > + if (err) { > + pr_err("Unable to setup input device keymap\n"); > + goto err_free_dev; > } > - > err = input_register_device(dell_wmi_aio_input_dev); > - > if (err) { > - input_free_device(dell_wmi_aio_input_dev); > - return err; > + pr_info("Unable to register input device\n"); > + goto err_free_keymap; > } > - > return 0; > + > +err_free_keymap: > + sparse_keymap_free(dell_wmi_aio_input_dev); > +err_free_dev: > + input_free_device(dell_wmi_aio_input_dev); > + return err; > } > > static char *dell_wmi_aio_find(void) > @@ -236,14 +149,13 @@ static int __init dell_wmi_aio_init(void) > return err; > > err = wmi_install_notify_handler(guid, > - dell_wmi_aio_notify, NULL); > + dell_wmi_aio_notify, NULL); > if (err) { > input_unregister_device(dell_wmi_aio_input_dev); > pr_err(AIO_PREFIX "Unable to register" > " notify handler - %d\n", err); > return err; > } > - > } else > pr_warning(AIO_PREFIX "No known WMI GUID found\n"); > Acked-by: Brad Figg<brad.figg@canonical.com>
diff --git a/drivers/platform/x86/dell-wmi-aio.c b/drivers/platform/x86/dell-wmi-aio.c index e770cb3..755c6d2 100644 --- a/drivers/platform/x86/dell-wmi-aio.c +++ b/drivers/platform/x86/dell-wmi-aio.c @@ -21,6 +21,7 @@ #include <linux/init.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> @@ -46,99 +47,14 @@ MODULE_ALIAS("dmi:*:*Dell*:*:"); MODULE_ALIAS("wmi:"EVENT_GUID1); MODULE_ALIAS("wmi:"EVENT_GUID2); -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_wmi_aio_keymap[] = { - { KE_KEY, 0xc0, KEY_VOLUMEUP }, - { KE_KEY, 0xc1, KEY_VOLUMEDOWN }, + { KE_KEY, 0xc0, { KEY_VOLUMEUP } }, + { KE_KEY, 0xc1, { KEY_VOLUMEDOWN } }, { KE_END, 0 } }; static struct input_dev *dell_wmi_aio_input_dev; -static struct key_entry *dell_wmi_aio_get_entry_by_scancode(int code) -{ - struct key_entry *key; - - for (key = dell_wmi_aio_keymap; key->type != KE_END; key++) - if (code == key->code) - return key; - - return NULL; -} - -static struct key_entry *dell_wmi_aio_get_entry_by_keycode(int keycode) -{ - struct key_entry *key; - - for (key = dell_wmi_aio_keymap; key->type != KE_END; key++) - if (key->type == KE_KEY && keycode == key->keycode) - return key; - - return NULL; -} - -static int dell_wmi_aio_getkeycode(struct input_dev *dev, int scancode, - int *keycode) -{ - struct key_entry *key = dell_wmi_aio_get_entry_by_scancode(scancode); - - if (key && key->type == KE_KEY) { - *keycode = key->keycode; - return 0; - } - - return -EINVAL; -} - -static int dell_wmi_aio_setkeycode(struct input_dev *dev, int scancode, - int keycode) -{ - struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - - key = dell_wmi_aio_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_aio_get_entry_by_keycode(old_keycode)) - clear_bit(old_keycode, dev->keybit); - return 0; - } - return -EINVAL; -} - -static void dell_wmi_aio_handle_key(unsigned int scancode) -{ - static struct key_entry *key; - - key = dell_wmi_aio_get_entry_by_scancode(scancode); - if (key) { - input_report_key(dell_wmi_aio_input_dev, key->keycode, 1); - input_sync(dell_wmi_aio_input_dev); - input_report_key(dell_wmi_aio_input_dev, key->keycode, 0); - input_sync(dell_wmi_aio_input_dev); - } else if (scancode) - pr_info(AIO_PREFIX "Unknown key %x pressed\n", - scancode); -} - static void dell_wmi_aio_notify(u32 value, void *context) { struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -159,13 +75,16 @@ static void dell_wmi_aio_notify(u32 value, void *context) case ACPI_TYPE_INTEGER: /* Most All-In-One correctly return integer scancode */ scancode = obj->integer.value; - dell_wmi_aio_handle_key(scancode); + sparse_keymap_report_event(dell_wmi_aio_input_dev, + scancode, 1, true); break; case ACPI_TYPE_BUFFER: /* Broken machines return the scancode in a buffer */ if (obj->buffer.pointer && obj->buffer.length > 0) { scancode = obj->buffer.pointer[0]; - dell_wmi_aio_handle_key(scancode); + sparse_keymap_report_event( + dell_wmi_aio_input_dev, + scancode, 1, true); } break; } @@ -175,7 +94,6 @@ static void dell_wmi_aio_notify(u32 value, void *context) static int __init dell_wmi_aio_input_setup(void) { - struct key_entry *key; int err; dell_wmi_aio_input_dev = input_allocate_device(); @@ -186,30 +104,25 @@ static int __init dell_wmi_aio_input_setup(void) dell_wmi_aio_input_dev->name = "Dell AIO WMI hotkeys"; dell_wmi_aio_input_dev->phys = "wmi/input0"; dell_wmi_aio_input_dev->id.bustype = BUS_HOST; - dell_wmi_aio_input_dev->getkeycode = dell_wmi_aio_getkeycode; - dell_wmi_aio_input_dev->setkeycode = dell_wmi_aio_setkeycode; - for (key = dell_wmi_aio_keymap; key->type != KE_END; key++) { - switch (key->type) { - case KE_KEY: - set_bit(EV_KEY, dell_wmi_aio_input_dev->evbit); - set_bit(key->keycode, dell_wmi_aio_input_dev->keybit); - break; - case KE_SW: - set_bit(EV_SW, dell_wmi_aio_input_dev->evbit); - set_bit(key->keycode, dell_wmi_aio_input_dev->swbit); - break; - } + err = sparse_keymap_setup(dell_wmi_aio_input_dev, + dell_wmi_aio_keymap, NULL); + if (err) { + pr_err("Unable to setup input device keymap\n"); + goto err_free_dev; } - err = input_register_device(dell_wmi_aio_input_dev); - if (err) { - input_free_device(dell_wmi_aio_input_dev); - return err; + pr_info("Unable to register input device\n"); + goto err_free_keymap; } - return 0; + +err_free_keymap: + sparse_keymap_free(dell_wmi_aio_input_dev); +err_free_dev: + input_free_device(dell_wmi_aio_input_dev); + return err; } static char *dell_wmi_aio_find(void) @@ -236,14 +149,13 @@ static int __init dell_wmi_aio_init(void) return err; err = wmi_install_notify_handler(guid, - dell_wmi_aio_notify, NULL); + dell_wmi_aio_notify, NULL); if (err) { input_unregister_device(dell_wmi_aio_input_dev); pr_err(AIO_PREFIX "Unable to register" " notify handler - %d\n", err); return err; } - } else pr_warning(AIO_PREFIX "No known WMI GUID found\n");