Patchwork [2/2] UBUNTU: SAUCE: Dell WMI: Use sparse keymaps and tidy up code.

login
register
mail settings
Submitter Colin King
Date Jan. 11, 2011, 4:42 p.m.
Message ID <1294764176-9760-3-git-send-email-colin.king@canonical.com>
Download mbox | patch
Permalink /patch/78412/
State Accepted
Delegated to: Brad Figg
Headers show

Comments

Colin King - Jan. 11, 2011, 4:42 p.m.
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(-)
Brad Figg - Jan. 11, 2011, 11:08 p.m.
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>

Patch

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");