[PATCH 1/2] UBUNTU: SAUCE: Add WMI hotkeys support for another Dell All-In-One series
Brad Figg
brad.figg at canonical.com
Tue Jan 11 23:08:04 UTC 2011
On 01/11/2011 10:42 AM, Colin King wrote:
> From: Colin Ian King<colin.king at canonical.com>
>
> Enable WMI hotkeys on event GUID 02314822-307C-4F66-bf0E-48AEAEB26CC8. This
> enables the volume up and down keys. This Dell All-In-One enablement also works
> around an implementation bug where the _WED method should return an integer
> containing the key code and in fact the method returns the key code in element
> zero of a buffer.
>
> BugLink: http://bugs.launchpad.net/bugs/701530
>
> Signed-off-by: Colin Ian King<colin.king at canonical.com>
> ---
> drivers/platform/x86/dell-wmi-aio.c | 84 +++++++++++++++++++++++++---------
> 1 files changed, 62 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/platform/x86/dell-wmi-aio.c b/drivers/platform/x86/dell-wmi-aio.c
> index c693473..e770cb3 100644
> --- a/drivers/platform/x86/dell-wmi-aio.c
> +++ b/drivers/platform/x86/dell-wmi-aio.c
> @@ -30,14 +30,22 @@
> MODULE_DESCRIPTION("WMI hotkeys driver for Dell All-In-One series");
> MODULE_LICENSE("GPL");
>
> -#define EVENT_GUID "284A0E6B-380E-472A-921F-E52786257FB4"
> +#define EVENT_GUID1 "284A0E6B-380E-472A-921F-E52786257FB4"
> +#define EVENT_GUID2 "02314822-307C-4F66-bf0E-48AEAEB26CC8"
>
> -MODULE_ALIAS("wmi:"EVENT_GUID);
> +static char *dell_wmi_aio_guids[] = {
> + EVENT_GUID1,
> + EVENT_GUID2,
> + NULL
> +};
>
> /* Temporary workaround until the WMI sysfs interface goes in.
> Borrowed from acer-wmi */
> MODULE_ALIAS("dmi:*:*Dell*:*:");
>
> +MODULE_ALIAS("wmi:"EVENT_GUID1);
> +MODULE_ALIAS("wmi:"EVENT_GUID2);
> +
> struct key_entry {
> char type; /* See KE_* below */
> u16 code;
> @@ -116,10 +124,24 @@ static int dell_wmi_aio_setkeycode(struct input_dev *dev, int scancode,
> 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 };
> - static struct key_entry *key;
> union acpi_object *obj;
> acpi_status status;
>
> @@ -130,21 +152,23 @@ static void dell_wmi_aio_notify(u32 value, void *context)
> }
>
> obj = (union acpi_object *)response.pointer;
> -
> - if (obj&& obj->type == ACPI_TYPE_INTEGER) {
> - int scancode = obj->integer.value;
> -
> - 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);
> + if (obj) {
> + unsigned int scancode;
> +
> + switch (obj->type) {
> + case ACPI_TYPE_INTEGER:
> + /* Most All-In-One correctly return integer scancode */
> + scancode = obj->integer.value;
> + dell_wmi_aio_handle_key(scancode);
> + 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);
> + }
> + break;
> + }
> }
> kfree(obj);
> }
> @@ -188,17 +212,30 @@ static int __init dell_wmi_aio_input_setup(void)
> return 0;
> }
>
> +static char *dell_wmi_aio_find(void)
> +{
> + int i;
> +
> + for (i = 0; dell_wmi_aio_guids[i] != NULL; i++)
> + if (wmi_has_guid(dell_wmi_aio_guids[i]))
> + return dell_wmi_aio_guids[i];
> +
> + return NULL;
> +}
> +
> static int __init dell_wmi_aio_init(void)
> {
> int err;
> + char *guid;
>
> - if (wmi_has_guid(EVENT_GUID)) {
> + guid = dell_wmi_aio_find();
> + if (guid) {
> err = dell_wmi_aio_input_setup();
>
> if (err)
> return err;
>
> - err = wmi_install_notify_handler(EVENT_GUID,
> + err = wmi_install_notify_handler(guid,
> dell_wmi_aio_notify, NULL);
> if (err) {
> input_unregister_device(dell_wmi_aio_input_dev);
> @@ -215,8 +252,11 @@ static int __init dell_wmi_aio_init(void)
>
> static void __exit dell_wmi_aio_exit(void)
> {
> - if (wmi_has_guid(EVENT_GUID)) {
> - wmi_remove_notify_handler(EVENT_GUID);
> + char *guid;
> +
> + guid = dell_wmi_aio_find();
> + if (guid) {
> + wmi_remove_notify_handler(guid);
> input_unregister_device(dell_wmi_aio_input_dev);
> }
> }
Acked-by: Brad Figg<brad.figg at canonical.com>
--
Brad Figg brad.figg at canonical.com http://www.canonical.com
More information about the kernel-team
mailing list