Discussion:
[PATCH 0/4] acer-wmi: Add new wmi support to acer-wmi driver
Lee, Chun-Yi
2010-12-07 02:29:19 UTC
Permalink
Hi Matthew,

These patches add new wmi support to acer-wmi driver, included the following
functions. Please kindly review and accept it:

- Acer wmi hotkey events:
Acer BIOS applied wmi hotkey events from 2010, this patch adds support.

- Enabled Acer Launch Manager mode:
Directly enable it to avoid the raw EC behavior conflict with rfkill-input or
userland solution.

- Add 3G rfkill sysfs file:
Provide interface to userland for enable/disable 3G function by wmi method.

- Detect the WiFi/Bluetooth/3G devices available:
Look for OEM type AAh in dmi to get the WiFi/BT/3G devices available.

Signed-off-by: Lee, Chun-Yi <***@novell.com>
Reviewed-by: Thomas Renninger <***@suse.de>

Lee, Chun-Yi (4):
Add acer wmi hotkey events support
Enabled Acer Launch Manager mode
Add 3G rfkill sysfs file
Detect the WiFi/Bluetooth/3G devices available

drivers/platform/x86/Kconfig | 2 +
drivers/platform/x86/acer-wmi.c | 400 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 394 insertions(+), 8 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Lee, Chun-Yi
2010-12-07 02:29:21 UTC
Permalink
Enabled Acer Launch Manager mode to disable the EC raw behavior for
communication devices when WMID3 method available. And, we also add a
ec_raw_mode kernel module option for enable The EC raw behavior mode
when anyone what reset it back.
When Acer Launch Manager mode enabled, EC will stop to touch any
communication devices' RF state or power state that causes conflict
with rfkill_input or any userland daemon to charge the rfkill rules.

Signed-off-by: Lee, Chun-Yi <***@novell.com>
Acked-by: Thomas Renninger <***@suse.de>
Acked-by: Jiri Benc <***@suse.cz>
Acked-by: Dmitry Torokhov <***@mail.ru>
Signed-off-by: Carlos Corbacho <***@strangeworlds.co.uk>
Cc: Corentin Chary <***@iksaif.net>
---
drivers/platform/x86/acer-wmi.c | 113 +++++++++++++++++++++++++++++++++++++++
1 files changed, 113 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 930df56..1568721 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -85,6 +85,7 @@ MODULE_LICENSE("GPL");
#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C"
#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"
#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A"
+#define WMID_GUID3 "61EF69EA-865C-4BC3-A502-A0DEBA0CB531"

/*
* Acer ACPI event GUIDs
@@ -120,6 +121,20 @@ struct event_return_value {
u32 reserved;
} __attribute__((packed));

+struct lm_input_params {
+ u8 function_num; /* Function Number */
+ u16 commun_devices; /* Communication type devices default status */
+ u16 devices; /* Other type devices default status */
+ u8 lm_status; /* Launch Manager Status */
+ u16 reserved;
+} __attribute__((packed));
+
+struct lm_return_value {
+ u8 error_code; /* Error Code */
+ u8 ec_return_value; /* EC Return Value */
+ u16 reserved;
+} __attribute__((packed));
+
/*
* Interface capability flags
*/
@@ -150,15 +165,18 @@ static int mailled = -1;
static int brightness = -1;
static int threeg = -1;
static int force_series;
+static bool ec_raw_mode;

module_param(mailled, int, 0444);
module_param(brightness, int, 0444);
module_param(threeg, int, 0444);
module_param(force_series, int, 0444);
+module_param(ec_raw_mode, bool, 0444);
MODULE_PARM_DESC(mailled, "Set initial state of Mail LED");
MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness");
MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware");
MODULE_PARM_DESC(force_series, "Force a different laptop series");
+MODULE_PARM_DESC(ec_raw_mode, "Enable EC raw mode");

struct acer_data {
int mailled;
@@ -1393,6 +1411,87 @@ error_debugfs:
return -ENOMEM;
}

+static acpi_status
+wmid3_set_lm_mode(struct lm_input_params *params,
+ struct lm_return_value *return_value)
+{
+ acpi_status status;
+ union acpi_object *obj;
+
+ struct acpi_buffer input = { sizeof(struct lm_input_params), params };
+ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+
+ status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ obj = output.pointer;
+
+ if (!obj)
+ return AE_ERROR;
+ else if (obj->type != ACPI_TYPE_BUFFER) {
+ kfree(obj);
+ return AE_ERROR;
+ }
+ if (obj->buffer.length != 4) {
+ printk(ACER_WARNING "Unknown buffer length %d\n",
+ obj->buffer.length);
+ kfree(obj);
+ return AE_ERROR;
+ }
+
+ *return_value = *((struct lm_return_value *)obj->buffer.pointer);
+ kfree(obj);
+
+ return status;
+}
+
+static int acer_wmi_enable_ec_raw(void)
+{
+ struct lm_return_value return_value;
+ acpi_status status;
+ struct lm_input_params params = {
+ .function_num = 0x1,
+ .commun_devices = 0xFFFF,
+ .devices = 0xFFFF,
+ .lm_status = 0x00, /* Launch Manager Deactive */
+ };
+
+ status = wmid3_set_lm_mode(&params, &return_value);
+
+ if (return_value.error_code || return_value.ec_return_value)
+ printk(ACER_WARNING "Enabling EC raw mode failed: "
+ "0x%x - 0x%x\n", return_value.error_code,
+ return_value.ec_return_value);
+ else
+ printk(ACER_INFO "Enabled EC raw mode");
+
+ return status;
+}
+
+static int acer_wmi_enable_lm(void)
+{
+ struct lm_return_value return_value;
+ acpi_status status;
+ struct lm_input_params params = {
+ .function_num = 0x1,
+ .commun_devices = 0x0041, /* WiFi on, 3G on, BT off */
+ .devices = 0xFFFF,
+ .lm_status = 0x41, /* Launch Manager Active */
+ };
+
+ status = wmid3_set_lm_mode(&params, &return_value);
+
+ if (return_value.error_code || return_value.ec_return_value)
+ printk(ACER_WARNING "Enabling Launch Manager failed: "
+ "0x%x - 0x%x\n", return_value.error_code,
+ return_value.ec_return_value);
+ else
+ printk(ACER_INFO "Enabled Launch Manager");
+
+ return status;
+}
+
static int __init acer_wmi_init(void)
{
int err;
@@ -1454,6 +1553,20 @@ static int __init acer_wmi_init(void)
"generic video driver\n");
}

+ if (wmi_has_guid(WMID_GUID3)) {
+ if (ec_raw_mode) {
+ if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) {
+ printk(ACER_ERR "Cannot enable EC raw mode\n");
+ return -ENODEV;
+ }
+ } else if (ACPI_FAILURE(acer_wmi_enable_lm())) {
+ printk(ACER_ERR "Cannot enable Launch Manager mode\n");
+ return -ENODEV;
+ }
+ } else if (ec_raw_mode) {
+ printk(ACER_INFO "No WMID EC raw mode enable method\n");
+ }
+
if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
err = acer_wmi_input_setup();
if (err)
--
1.6.0.2
Lee, Chun-Yi
2010-12-07 02:29:23 UTC
Permalink
Check the Acer OEM-specific Type AA to detect the WiFi/Bluetooth/3G
devices available or not, and set the devices capability flag.

Signed-off-by: Lee, Chun-Yi <***@novell.com>
Reviewed-by: Jean Delvare <***@suse.de>
Reviewed-by: Dmitry Torokhov <***@mail.ru>
Acked-by: Thomas Renninger <***@suse.de>
Acked-by: Jiri Benc <***@suse.cz>
Cc: Carlos Corbacho <***@strangeworlds.co.uk>
Cc: Corentin Chary <***@iksaif.net>
---
drivers/platform/x86/acer-wmi.c | 49 +++++++++++++++++++++++++++++++++-----
1 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 6ac4656..dc23140 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -39,6 +39,7 @@
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
+#include <linux/dmi.h>

#include <acpi/acpi_drivers.h>

@@ -138,7 +139,9 @@ struct lm_return_value {
/*
* GUID3 Get Device Status device flags
*/
+#define ACER_WMID3_GDS_WIRELESS (1<<0) /* WiFi */
#define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */
+#define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */

struct wmid3_gds_input_param { /* Get Device Status input parameter */
u8 function_num; /* Function Number */
@@ -153,6 +156,13 @@ struct wmid3_gds_return_value { /* Get Device Status return value*/
u32 reserved;
} __attribute__((packed));

+struct hotkey_function_type_aa {
+ u8 type;
+ u8 length;
+ u16 handle;
+ u16 commun_func_bitmap;
+} __attribute__((packed));
+
/*
* Interface capability flags
*/
@@ -184,6 +194,7 @@ static int brightness = -1;
static int threeg = -1;
static int force_series;
static bool ec_raw_mode;
+static bool has_type_aa;

module_param(mailled, int, 0444);
module_param(brightness, int, 0444);
@@ -824,6 +835,28 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
return WMI_execute_u32(method_id, (u32)value, NULL);
}

+static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
+{
+ struct hotkey_function_type_aa *type_aa;
+
+ /* We are looking for OEM-specific Type AAh */
+ if (header->type != 0xAA)
+ return;
+
+ has_type_aa = true;
+ type_aa = (struct hotkey_function_type_aa *) header;
+
+ printk(ACER_INFO "Function bitmap for Communication Button: 0x%x\n",
+ type_aa->commun_func_bitmap);
+
+ if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS)
+ interface->capability |= ACER_CAP_WIRELESS;
+ if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_THREEG)
+ interface->capability |= ACER_CAP_THREEG;
+ if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_BLUETOOTH)
+ interface->capability |= ACER_CAP_BLUETOOTH;
+}
+
static acpi_status WMID_set_capabilities(void)
{
struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
@@ -844,16 +877,17 @@ static acpi_status WMID_set_capabilities(void)
return AE_ERROR;
}

- /* Not sure on the meaning of the relevant bits yet to detect these */
- interface->capability |= ACER_CAP_WIRELESS;
- interface->capability |= ACER_CAP_THREEG;
+ dmi_walk(type_aa_dmi_decode, NULL);
+ if (!has_type_aa) {
+ interface->capability |= ACER_CAP_WIRELESS;
+ interface->capability |= ACER_CAP_THREEG;
+ if (devices & 0x10)
+ interface->capability |= ACER_CAP_BLUETOOTH;
+ }

/* WMID always provides brightness methods */
interface->capability |= ACER_CAP_BRIGHTNESS;

- if (devices & 0x10)
- interface->capability |= ACER_CAP_BLUETOOTH;
-
if (!(devices & 0x20))
max_brightness = 0x9;

@@ -932,7 +966,8 @@ static void __init acer_commandline_init(void)
* capability isn't available on the given interface
*/
set_u32(mailled, ACER_CAP_MAILLED);
- set_u32(threeg, ACER_CAP_THREEG);
+ if (!has_type_aa)
+ set_u32(threeg, ACER_CAP_THREEG);
set_u32(brightness, ACER_CAP_BRIGHTNESS);
}
--
1.6.0.2

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Lee, Chun-Yi
2010-12-07 02:29:22 UTC
Permalink
Add 3G rfkill sysfs file for provide userland to control 3G device
on/off by using WMI method.

Signed-off-by: Lee, Chun-Yi <***@novell.com>
Acked-by: Thomas Renninger <***@suse.de>
Acked-by: Jiri Benc <***@suse.cz>
Acked-by: Dmitry Torokhov <***@mail.ru>
Signed-off-by: Carlos Corbaho <***@strangeworlds.co.uk>
Cc: Corentin Chary <***@iksaif.net>
---
drivers/platform/x86/acer-wmi.c | 99 ++++++++++++++++++++++++++++++++++++++-
1 files changed, 98 insertions(+), 1 deletions(-)

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),
+ &params
+ };
+ 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 AE_ERROR;
+ else if (obj->type != ACPI_TYPE_BUFFER) {
+ kfree(obj);
+ return AE_ERROR;
+ }
+ if (obj->buffer.length != 8) {
+ printk(ACER_WARNING "Unknown buffer length %d\n",
+ obj->buffer.length);
+ kfree(obj);
+ return AE_ERROR;
+ }
+
+ 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");
--
1.6.0.2
Matthew Garrett
2010-12-20 16:06:12 UTC
Permalink
Post by Lee, Chun-Yi
+ struct lm_return_value return_value;
+ acpi_status status;
+ struct lm_input_params params = {
+ .function_num = 0x1,
+ .commun_devices = 0x0041, /* WiFi on, 3G on, BT off */
Why this set of devices?
Post by Lee, Chun-Yi
+ printk(ACER_INFO "Enabled Launch Manager");
This is the default behaviour, so I don't think you need to print
anything in this case.

The other patches in the series look fine - I'll apply those to -next
now.
--
Matthew Garrett | ***@srcf.ucam.org
Lee, Chun-Yi
2010-12-07 02:29:20 UTC
Permalink
Add acer wmi hotkey event support. Install a wmi notify handler to
transfer wmi event key to key code, then send out keycode through acer
wmi input device to userland.

Signed-off-by: Lee, Chun-Yi <***@novell.com>
Acked-by: Dmitry Torokhov <***@mail.ru>
Acked-by: Thomas Renninger <***@suse.de>
Acked-by: Jiri Benc <***@suse.cz>
Signed-off-by: Carlos Corbacho <***@strangeworlds.co.uk>
Cc: Corentin Chary <***@iksaif.net>
---
drivers/platform/x86/Kconfig | 2 +
drivers/platform/x86/acer-wmi.c | 139 +++++++++++++++++++++++++++++++++++++++
2 files changed, 141 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index cff7cc2..c242fdd 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -23,7 +23,9 @@ config ACER_WMI
depends on BACKLIGHT_CLASS_DEVICE
depends on SERIO_I8042
depends on RFKILL || RFKILL = n
+ depends on INPUT
select ACPI_WMI
+ select INPUT_SPARSEKMAP
---help---
This is a driver for newer Acer (and Wistron) laptops. It adds
wireless radio and bluetooth control, and on some laptops,
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 2badee2..930df56 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -37,6 +37,8 @@
#include <linux/workqueue.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>

#include <acpi/acpi_drivers.h>

@@ -48,6 +50,7 @@ MODULE_LICENSE("GPL");
#define ACER_ERR KERN_ERR ACER_LOGPREFIX
#define ACER_NOTICE KERN_NOTICE ACER_LOGPREFIX
#define ACER_INFO KERN_INFO ACER_LOGPREFIX
+#define ACER_WARNING KERN_WARNING ACER_LOGPREFIX

/*
* Magic Number
@@ -83,8 +86,39 @@ MODULE_LICENSE("GPL");
#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"
#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A"

+/*
+ * Acer ACPI event GUIDs
+ */
+#define ACERWMID_EVENT_GUID "676AA15E-6A47-4D9F-A2CC-1E6D18D14026"
+
MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB");
MODULE_ALIAS("wmi:6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3");
+MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026");
+
+enum acer_wmi_event_ids {
+ WMID_HOTKEY_EVENT = 0x1,
+};
+
+static const struct key_entry acer_wmi_keymap[] = {
+ {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */
+ {KE_KEY, 0x12, {KEY_BLUETOOTH} }, /* BT */
+ {KE_KEY, 0x21, {KEY_PROG1} }, /* Backup */
+ {KE_KEY, 0x22, {KEY_PROG2} }, /* Arcade */
+ {KE_KEY, 0x23, {KEY_PROG3} }, /* P_Key */
+ {KE_KEY, 0x24, {KEY_PROG4} }, /* Social networking_Key */
+ {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */
+ {KE_KEY, 0x82, {KEY_F22} }, /* Touch Pad On/Off */
+ {KE_END, 0}
+};
+
+static struct input_dev *acer_wmi_input_dev;
+
+struct event_return_value {
+ u8 function;
+ u8 key_num;
+ u16 device_state;
+ u32 reserved;
+} __attribute__((packed));

/*
* Interface capability flags
@@ -1085,6 +1119,99 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr,

static DEVICE_ATTR(interface, S_IRUGO, show_interface, NULL);

+static void acer_wmi_notify(u32 value, void *context)
+{
+ struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *obj;
+ struct event_return_value return_value;
+ acpi_status status;
+
+ status = wmi_get_event_data(value, &response);
+ if (status != AE_OK) {
+ printk(ACER_WARNING "bad event status 0x%x\n", status);
+ return;
+ }
+
+ obj = (union acpi_object *)response.pointer;
+
+ if (!obj)
+ return;
+ if (obj->type != ACPI_TYPE_BUFFER) {
+ printk(ACER_WARNING "Unknown response received %d\n",
+ obj->type);
+ kfree(obj);
+ return;
+ }
+ if (obj->buffer.length != 8) {
+ printk(ACER_WARNING "Unknown buffer length %d\n",
+ obj->buffer.length);
+ kfree(obj);
+ return;
+ }
+
+ return_value = *((struct event_return_value *)obj->buffer.pointer);
+ kfree(obj);
+
+ switch (return_value.function) {
+ case WMID_HOTKEY_EVENT:
+ if (!sparse_keymap_report_event(acer_wmi_input_dev,
+ return_value.key_num, 1, true))
+ printk(ACER_WARNING "Unknown key number - 0x%x\n",
+ return_value.key_num);
+ break;
+ default:
+ printk(ACER_WARNING "Unknown function number - %d - %d\n",
+ return_value.function, return_value.key_num);
+ break;
+ }
+}
+
+static int __init acer_wmi_input_setup(void)
+{
+ acpi_status status;
+ int err;
+
+ acer_wmi_input_dev = input_allocate_device();
+ if (!acer_wmi_input_dev)
+ return -ENOMEM;
+
+ acer_wmi_input_dev->name = "Acer WMI hotkeys";
+ acer_wmi_input_dev->phys = "wmi/input0";
+ acer_wmi_input_dev->id.bustype = BUS_HOST;
+
+ err = sparse_keymap_setup(acer_wmi_input_dev, acer_wmi_keymap, NULL);
+ if (err)
+ goto err_free_dev;
+
+ status = wmi_install_notify_handler(ACERWMID_EVENT_GUID,
+ acer_wmi_notify, NULL);
+ if (ACPI_FAILURE(status)) {
+ err = -EIO;
+ goto err_free_keymap;
+ }
+
+ err = input_register_device(acer_wmi_input_dev);
+ if (err)
+ goto err_uninstall_notifier;
+
+ return 0;
+
+err_uninstall_notifier:
+ wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
+err_free_keymap:
+ sparse_keymap_free(acer_wmi_input_dev);
+err_free_dev:
+ input_free_device(acer_wmi_input_dev);
+ return err;
+}
+
+static void acer_wmi_input_destroy(void)
+{
+ wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
+ sparse_keymap_free(acer_wmi_input_dev);
+ input_unregister_device(acer_wmi_input_dev);
+}
+
/*
* debugfs functions
*/
@@ -1327,6 +1454,12 @@ static int __init acer_wmi_init(void)
"generic video driver\n");
}

+ if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
+ err = acer_wmi_input_setup();
+ if (err)
+ return err;
+ }
+
err = platform_driver_register(&acer_platform_driver);
if (err) {
printk(ACER_ERR "Unable to register platform driver.\n");
@@ -1368,11 +1501,17 @@ error_device_add:
error_device_alloc:
platform_driver_unregister(&acer_platform_driver);
error_platform_register:
+ if (wmi_has_guid(ACERWMID_EVENT_GUID))
+ acer_wmi_input_destroy();
+
return err;
}

static void __exit acer_wmi_exit(void)
{
+ if (wmi_has_guid(ACERWMID_EVENT_GUID))
+ acer_wmi_input_destroy();
+
remove_sysfs(acer_platform_device);
remove_debugfs();
platform_device_unregister(acer_platform_device);
--
1.6.0.2
Joey Lee
2010-12-21 03:30:58 UTC
Permalink
Hi Matthew,=20

=E6=96=BC =E4=B8=80=EF=BC=8C2010-12-20 =E6=96=BC 16:06 +0000=EF=BC=8CMa=
tthew Garrett =E6=8F=90=E5=88=B0=EF=BC=9A
Post by Matthew Garrett
Post by Lee, Chun-Yi
+ struct lm_return_value return_value;
+ acpi_status status;
+ struct lm_input_params params =3D {
+ .function_num =3D 0x1,
+ .commun_devices =3D 0x0041, /* WiFi on, 3G on, BT off */
=20
Why this set of devices?
=20
The default Acer's BIOS default config is WiFi on, 3G on, BT off.
Originally, I want to set the default devices status for communication
devices to sync with Acer's BIOS default config.

But,=20
current Acer BIOS still not support to set the default communication
devices' state and it ignored my config when acer-wmi call wmi method t=
o
enable launch manager mode.=20

I modified the patch to removed the non-used communication devices setu=
p
like following:

+static int acer_wmi_enable_lm(void)
+{
+ struct lm_return_value return_value;
+ acpi_status status;
+ struct lm_input_params params =3D {
+ .function_num =3D 0x1,
+ .commun_devices =3D 0xFFFF,
+ .devices =3D 0xFFFF,
+ .lm_status =3D 0x01, /* Launch Manager Act=
ive */
Post by Matthew Garrett
Post by Lee, Chun-Yi
+ printk(ACER_INFO "Enabled Launch Manager");
=20
This is the default behaviour, so I don't think you need to print=20
anything in this case.
=20
OK, then me removed it.
Post by Matthew Garrett
The other patches in the series look fine - I'll apply those to -next=
=20
Post by Matthew Garrett
now.
=20
Thank's a lot for your take care, the following is new [PATCH 2/4] for
review:

Joey Lee
Post by Matthew Garrett
From 79dea6e0d647f39f2a3b2837d992daab333fa577 Mon Sep 17 00:00:00 2001
=46rom: Lee, Chun-Yi <***@novell.com>
Date: Tue, 21 Dec 2010 11:15:02 +0800
Subject: [PATCH 2/4] acer-wmi: Enabled Acer Launch Manager mode

Enabled Acer Launch Manager mode to disable the EC raw behavior for
communication devices when WMID3 method available. And, we also add a
ec_raw_mode kernel module option for enable The EC raw behavior mode
when anyone what reset it back.
When Acer Launch Manager mode enabled, EC will stop to touch any
communication devices' RF state or power state that causes conflict
with rfkill_input or any userland daemon to charge the rfkill rules.

Signed-off-by: Lee, Chun-Yi <***@novell.com>
Acked-by: Thomas Renninger <***@suse.de>
Acked-by: Jiri Benc <***@suse.cz>
Acked-by: Dmitry Torokhov <***@mail.ru>
Signed-off-by: Carlos Corbacho <***@strangeworlds.co.uk>
Cc: Corentin Chary <***@iksaif.net>
---
drivers/platform/x86/acer-wmi.c | 111 +++++++++++++++++++++++++++++++=
++++++++
1 files changed, 111 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/ace=
r-wmi.c
index 94330d7..81c1808 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -85,6 +85,7 @@ MODULE_LICENSE("GPL");
#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C"
#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"
#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A"
+#define WMID_GUID3 "61EF69EA-865C-4BC3-A502-A0DEBA0CB531"
=20
/*
* Acer ACPI event GUIDs
@@ -120,6 +121,20 @@ struct event_return_value {
u32 reserved;
} __attribute__((packed));
=20
+struct lm_input_params {
+ u8 function_num; /* Function Number */
+ u16 commun_devices; /* Communication type devices default status */
+ u16 devices; /* Other type devices default status */
+ u8 lm_status; /* Launch Manager Status */
+ u16 reserved;
+} __attribute__((packed));
+
+struct lm_return_value {
+ u8 error_code; /* Error Code */
+ u8 ec_return_value; /* EC Return Value */
+ u16 reserved;
+} __attribute__((packed));
+
/*
* Interface capability flags
*/
@@ -150,15 +165,18 @@ static int mailled =3D -1;
static int brightness =3D -1;
static int threeg =3D -1;
static int force_series;
+static bool ec_raw_mode;
=20
module_param(mailled, int, 0444);
module_param(brightness, int, 0444);
module_param(threeg, int, 0444);
module_param(force_series, int, 0444);
+module_param(ec_raw_mode, bool, 0444);
MODULE_PARM_DESC(mailled, "Set initial state of Mail LED");
MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness");
MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware");
MODULE_PARM_DESC(force_series, "Force a different laptop series");
+MODULE_PARM_DESC(ec_raw_mode, "Enable EC raw mode");
=20
struct acer_data {
int mailled;
@@ -1393,6 +1411,85 @@ error_debugfs:
return -ENOMEM;
}
=20
+static acpi_status
+wmid3_set_lm_mode(struct lm_input_params *params,
+ struct lm_return_value *return_value)
+{
+ acpi_status status;
+ union acpi_object *obj;
+
+ struct acpi_buffer input =3D { sizeof(struct lm_input_params), params=
};
+ struct acpi_buffer output =3D { ACPI_ALLOCATE_BUFFER, NULL };
+
+ status =3D wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ obj =3D output.pointer;
+
+ if (!obj)
+ return AE_ERROR;
+ else if (obj->type !=3D ACPI_TYPE_BUFFER) {
+ kfree(obj);
+ return AE_ERROR;
+ }
+ if (obj->buffer.length !=3D 4) {
+ printk(ACER_WARNING "Unknown buffer length %d\n",
+ obj->buffer.length);
+ kfree(obj);
+ return AE_ERROR;
+ }
+
+ *return_value =3D *((struct lm_return_value *)obj->buffer.pointer);
+ kfree(obj);
+
+ return status;
+}
+
+static int acer_wmi_enable_ec_raw(void)
+{
+ struct lm_return_value return_value;
+ acpi_status status;
+ struct lm_input_params params =3D {
+ .function_num =3D 0x1,
+ .commun_devices =3D 0xFFFF,
+ .devices =3D 0xFFFF,
+ .lm_status =3D 0x00, /* Launch Manager Deactive */
+ };
+
+ status =3D wmid3_set_lm_mode(&params, &return_value);
+
+ if (return_value.error_code || return_value.ec_return_value)
+ printk(ACER_WARNING "Enabling EC raw mode failed: "
+ "0x%x - 0x%x\n", return_value.error_code,
+ return_value.ec_return_value);
+ else
+ printk(ACER_INFO "Enabled EC raw mode");
+
+ return status;
+}
+
+static int acer_wmi_enable_lm(void)
+{
+ struct lm_return_value return_value;
+ acpi_status status;
+ struct lm_input_params params =3D {
+ .function_num =3D 0x1,
+ .commun_devices =3D 0xFFFF,
+ .devices =3D 0xFFFF,
+ .lm_status =3D 0x01, /* Launch Manager Active */
+ };
+
+ status =3D wmid3_set_lm_mode(&params, &return_value);
+
+ if (return_value.error_code || return_value.ec_return_value)
+ printk(ACER_WARNING "Enabling Launch Manager failed: "
+ "0x%x - 0x%x\n", return_value.error_code,
+ return_value.ec_return_value);
+
+ return status;
+}
+
static int __init acer_wmi_init(void)
{
int err;
@@ -1454,6 +1551,20 @@ static int __init acer_wmi_init(void)
"generic video driver\n");
}
=20
+ if (wmi_has_guid(WMID_GUID3)) {
+ if (ec_raw_mode) {
+ if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) {
+ printk(ACER_ERR "Cannot enable EC raw mode\n");
+ return -ENODEV;
+ }
+ } else if (ACPI_FAILURE(acer_wmi_enable_lm())) {
+ printk(ACER_ERR "Cannot enable Launch Manager mode\n");
+ return -ENODEV;
+ }
+ } else if (ec_raw_mode) {
+ printk(ACER_INFO "No WMID EC raw mode enable method\n");
+ }
+
if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
err =3D acer_wmi_input_setup();
if (err)
--=20
1.6.0.2
Matthew Garrett
2011-01-07 22:27:58 UTC
Permalink
Applied, thanks.
--
Matthew Garrett | ***@srcf.ucam.org
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Loading...