From patchwork Fri Jul 31 02:26:47 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Garrett X-Patchwork-Id: 38439 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n6V2QxGS010782 for ; Fri, 31 Jul 2009 02:26:59 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752479AbZGaC04 (ORCPT ); Thu, 30 Jul 2009 22:26:56 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752614AbZGaC04 (ORCPT ); Thu, 30 Jul 2009 22:26:56 -0400 Received: from cavan.codon.org.uk ([93.93.128.6]:47483 "EHLO cavan.codon.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752479AbZGaC0z (ORCPT ); Thu, 30 Jul 2009 22:26:55 -0400 Received: from 78-86-230-144.zone2.bethere.co.uk ([78.86.230.144] helo=localhost.localdomain) by cavan.codon.org.uk with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1MWhpd-0007KA-T1; Fri, 31 Jul 2009 03:26:53 +0100 From: Matthew Garrett To: linux-acpi@vger.kernel.org Cc: linux-input@vger.kernel.org, dmitry.torokhov@gmail.com, Matthew Garrett Subject: [PATCH 2/2] dell-laptop: Trigger rfkill updates on wifi toggle switch press Date: Fri, 31 Jul 2009 03:26:47 +0100 Message-Id: <1249007207-27392-2-git-send-email-mjg@redhat.com> X-Mailer: git-send-email 1.6.2.5 In-Reply-To: <1249007207-27392-1-git-send-email-mjg@redhat.com> References: <1249007207-27392-1-git-send-email-mjg@redhat.com> X-SA-Do-Not-Run: Yes X-SA-Exim-Connect-IP: 78.86.230.144 X-SA-Exim-Mail-From: mjg@redhat.com X-SA-Exim-Scanned: No (on cavan.codon.org.uk); SAEximRunCond expanded to false Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Dell hardware sends the rfkill hardware killswitch event via the keyboard controller, even if it's a physical toggle switch on the side of the machine. Add support for catching the input event and updating the rfkill state, allowing userspace to receive notifications that the change has occurred. Signed-off-by: Matthew Garrett --- drivers/platform/x86/dell-laptop.c | 100 ++++++++++++++++++++++++++++++++++++ 1 files changed, 100 insertions(+), 0 deletions(-) diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 74909c4..71a4149 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "../../firmware/dcdbas.h" #define BRIGHTNESS_TOKEN 0x7d @@ -206,6 +207,16 @@ static const struct rfkill_ops dell_rfkill_ops = { .query = dell_rfkill_query, }; +static void dell_rfkill_update(void) +{ + if (wifi_rfkill) + dell_rfkill_query(wifi_rfkill, (void *)1); + if (bluetooth_rfkill) + dell_rfkill_query(bluetooth_rfkill, (void *)2); + if (wwan_rfkill) + dell_rfkill_query(wwan_rfkill, (void *)3); +} + static int dell_setup_rfkill(void) { struct calling_interface_buffer buffer; @@ -310,6 +321,90 @@ static struct backlight_ops dell_ops = { .update_status = dell_send_intensity, }; +static const struct input_device_id dell_input_ids[] = { + { + .bustype = 0x11, + .vendor = 0x01, + .product = 0x01, + .version = 0xab41, + .flags = INPUT_DEVICE_ID_MATCH_BUS | + INPUT_DEVICE_ID_MATCH_VENDOR | + INPUT_DEVICE_ID_MATCH_PRODUCT | + INPUT_DEVICE_ID_MATCH_VERSION + }, + { }, +}; + +static bool dell_input_filter(struct input_handle *handle, unsigned int type, + unsigned int code, int value) +{ + if (type == EV_KEY && code == KEY_WLAN && value == 1) { + dell_rfkill_update(); + return 1; + } + + return 0; +} + +static void dell_input_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) +{ +} + +static int dell_input_connect(struct input_handler *handler, + struct input_dev *dev, + const struct input_device_id *id) +{ + struct input_handle *handle; + int error; + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "dell-laptop"; + + error = input_register_handle(handle); + if (error) + goto err_free_handle; + + error = input_open_device(handle); + if (error) + goto err_unregister_handle; + + error = input_filter_device(handle); + if (error) + goto err_close_handle; + + return 0; + +err_close_handle: + input_close_device(handle); +err_unregister_handle: + input_unregister_handle(handle); +err_free_handle: + kfree(handle); + return error; +} + +static void dell_input_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static struct input_handler dell_input_handler = { + .name = "dell-laptop", + .filter = dell_input_filter, + .event = dell_input_event, + .connect = dell_input_connect, + .disconnect = dell_input_disconnect, + .id_table = dell_input_ids, +}; + static int __init dell_init(void) { struct calling_interface_buffer buffer; @@ -333,6 +428,10 @@ static int __init dell_init(void) goto out; } + if (input_register_handler(&dell_input_handler)) + printk(KERN_INFO + "dell-laptop: Could not register input filter\n"); + #ifdef CONFIG_ACPI /* In the event of an ACPI backlight being available, don't * register the platform controller. @@ -388,6 +487,7 @@ static void __exit dell_exit(void) rfkill_unregister(bluetooth_rfkill); if (wwan_rfkill) rfkill_unregister(wwan_rfkill); + input_unregister_handler(&dell_input_handler); } module_init(dell_init);