From patchwork Sat Dec 4 01:03:25 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chun-Yi Lee X-Patchwork-Id: 379841 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oB4155I8002794 for ; Sat, 4 Dec 2010 01:05:24 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753671Ab0LDBFX (ORCPT ); Fri, 3 Dec 2010 20:05:23 -0500 Received: from mail-wy0-f174.google.com ([74.125.82.174]:54022 "EHLO mail-wy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753873Ab0LDBFX (ORCPT ); Fri, 3 Dec 2010 20:05:23 -0500 Received: by mail-wy0-f174.google.com with SMTP id 28so10075591wyb.19 for ; Fri, 03 Dec 2010 17:05:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:subject:date :message-id:x-mailer:in-reply-to:references; bh=Y3kBPGPLqVJFcmIgCZw7MCxID6CJvwlkCWCjnF4uDZg=; b=uyZnW+O+TXTyXlaHyLLmiQ5pHGOXCt/72S8qvqab1p3W3Yl+G0rexK5HfjjjBxMbiP JBSprLfAQpGqKu8vCWOMCgoz+eQnVPeRmQOoWpYtJgRye35JOwA215nQfYIw47F12Dsx 6mOkDTIzEbnhvzRKTaEidVJ+xOHvudph/YcS4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=IvQZwTyyNoIm2d/Pbyjuu1D+RRcOh9Oliimegh6uFq/Ea/TEIBO/6l8NrQXtYKN+S3 3nFfPU0OogqXUhUiXhfR8R5b6MkJl2uFmTGQB8VLNwDeZrmtCpukdNLGTIXdf8VK88cs ulC1zQw83wW8tU7wyIAKsf9uxyqwZ6uDgbjgM= Received: by 10.227.141.205 with SMTP id n13mr2733684wbu.28.1291424721393; Fri, 03 Dec 2010 17:05:21 -0800 (PST) Received: from localhost.localdomain (124-11-22-254.dynamic.tfn.net.tw [124.11.22.254]) by mx.google.com with ESMTPS id m10sm1686256wbc.16.2010.12.03.17.05.15 (version=SSLv3 cipher=RC4-MD5); Fri, 03 Dec 2010 17:05:20 -0800 (PST) From: "Lee, Chun-Yi" To: mjg@redhat.com Cc: carlos@strangeworlds.co.uk, corentin.chary@gmail.com, dmitry.torokhov@gmail.com, corentincj@iksaif.net, tiwai@novell.com, mjg59@srcf.ucam.org, jbenc@suse.cz, jdelvare@suse.de, trenn@suse.de, platform-driver-x86@vger.kernel.org, linux-input@vger.kernel.org, "Lee, Chun-Yi" , Dmitry Torokhov Subject: [PATCH 3/4] Add 3G rfkill sysfs file Date: Sat, 4 Dec 2010 09:03:25 +0800 Message-Id: <1291424606-23383-4-git-send-email-jlee@novell.com> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: <1291424606-23383-3-git-send-email-jlee@novell.com> References: <1291424606-23383-1-git-send-email-jlee@novell.com> <1291424606-23383-2-git-send-email-jlee@novell.com> <1291424606-23383-3-git-send-email-jlee@novell.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Sat, 04 Dec 2010 01:05:24 +0000 (UTC) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 1568721..6ac4656 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -136,6 +136,24 @@ struct lm_return_value { } __attribute__((packed)); /* + * GUID3 Get Device Status device flags + */ +#define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */ + +struct wmid3_gds_input_param { /* Get Device Status input parameter */ + u8 function_num; /* Function Number */ + u8 hotkey_number; /* Hotkey Number */ + u16 devices; /* Get Device */ +} __attribute__((packed)); + +struct wmid3_gds_return_value { /* Get Device Status return value*/ + u8 error_code; /* Error Code */ + u8 ec_return_value; /* EC Return Value */ + u16 devices; /* Current Device Status */ + u32 reserved; +} __attribute__((packed)); + +/* * Interface capability flags */ #define ACER_CAP_MAILLED (1<<0) @@ -192,6 +210,7 @@ struct acer_debug { static struct rfkill *wireless_rfkill; static struct rfkill *bluetooth_rfkill; +static struct rfkill *threeg_rfkill; /* Each low-level interface must define at least some of the following */ struct wmi_interface { @@ -1000,6 +1019,54 @@ static void acer_backlight_exit(void) backlight_device_unregister(acer_backlight_device); } +static acpi_status wmid3_get_device_status(u32 *value, u16 device) +{ + struct wmid3_gds_return_value return_value; + acpi_status status; + union acpi_object *obj; + struct wmid3_gds_input_param params = { + .function_num = 0x1, + .hotkey_number = 0x01, + .devices = device, + }; + struct acpi_buffer input = { + sizeof(struct wmid3_gds_input_param), + ¶ms + }; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + + status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output); + if (ACPI_FAILURE(status)) + return status; + + obj = output.pointer; + + if (!obj) + return -EINVAL; + else if (obj->type != ACPI_TYPE_BUFFER) { + kfree(obj); + return -EINVAL; + } + if (obj->buffer.length != 8) { + printk(ACER_WARNING "Unknown buffer length %d\n", + obj->buffer.length); + kfree(obj); + return -EINVAL; + } + + return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer); + kfree(obj); + + if (return_value.error_code || return_value.ec_return_value) + printk(ACER_WARNING "Get Device Status failed: " + "0x%x - 0x%x\n", return_value.error_code, + return_value.ec_return_value); + else + *value = !!(return_value.devices & device); + + return status; +} + /* * Rfkill devices */ @@ -1020,6 +1087,13 @@ static void acer_rfkill_update(struct work_struct *ignored) rfkill_set_sw_state(bluetooth_rfkill, !state); } + if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) { + status = wmid3_get_device_status(&state, + ACER_WMID3_GDS_THREEG); + if (ACPI_SUCCESS(status)) + rfkill_set_sw_state(threeg_rfkill, !state); + } + schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); } @@ -1076,6 +1150,19 @@ static int acer_rfkill_init(struct device *dev) } } + if (has_cap(ACER_CAP_THREEG)) { + threeg_rfkill = acer_rfkill_register(dev, + RFKILL_TYPE_WWAN, "acer-threeg", + ACER_CAP_THREEG); + if (IS_ERR(threeg_rfkill)) { + rfkill_unregister(wireless_rfkill); + rfkill_destroy(wireless_rfkill); + rfkill_unregister(bluetooth_rfkill); + rfkill_destroy(bluetooth_rfkill); + return PTR_ERR(threeg_rfkill); + } + } + schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); return 0; @@ -1092,6 +1179,11 @@ static void acer_rfkill_exit(void) rfkill_unregister(bluetooth_rfkill); rfkill_destroy(bluetooth_rfkill); } + + if (has_cap(ACER_CAP_THREEG)) { + rfkill_unregister(threeg_rfkill); + rfkill_destroy(threeg_rfkill); + } return; } @@ -1102,7 +1194,12 @@ static ssize_t show_bool_threeg(struct device *dev, struct device_attribute *attr, char *buf) { u32 result; \ - acpi_status status = get_u32(&result, ACER_CAP_THREEG); + acpi_status status; + if (wmi_has_guid(WMID_GUID3)) + status = wmid3_get_device_status(&result, + ACER_WMID3_GDS_THREEG); + else + status = get_u32(&result, ACER_CAP_THREEG); if (ACPI_SUCCESS(status)) return sprintf(buf, "%u\n", result); return sprintf(buf, "Read error\n");