From patchwork Wed Feb 9 18:17:54 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Colin Ian King X-Patchwork-Id: 82508 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id 21392B70E9 for ; Thu, 10 Feb 2011 05:18:08 +1100 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1PnEc5-0001um-Ba; Wed, 09 Feb 2011 18:18:01 +0000 Received: from adelie.canonical.com ([91.189.90.139]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1PnEc3-0001ua-KB for kernel-team@lists.ubuntu.com; Wed, 09 Feb 2011 18:17:59 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by adelie.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1PnEc3-0002uM-Hc for ; Wed, 09 Feb 2011 18:17:59 +0000 Received: from cpc7-craw6-2-0-cust128.croy.cable.virginmedia.com ([94.172.219.129] helo=localhost) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1PnEc3-0002GW-00 for kernel-team@lists.ubuntu.com; Wed, 09 Feb 2011 18:17:59 +0000 From: Colin King To: kernel-team@lists.ubuntu.com Subject: [PATCH 2/3] UBUNTU: SAUCE: Add WMI hotkeys support for another Dell All-In-One series Date: Wed, 9 Feb 2011 18:17:54 +0000 Message-Id: <1297275475-31429-3-git-send-email-colin.king@canonical.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1297275475-31429-1-git-send-email-colin.king@canonical.com> References: <1297275475-31429-1-git-send-email-colin.king@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com From: Colin Ian King 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 Acked-by: Brad Figg --- 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); } }