linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] Add acer wmi hotkey events support
@ 2010-10-01 13:51 Lee, Chun-Yi
  2010-10-01 13:51 ` [PATCH 2/2] Support enable Acer Launch Manager mode Lee, Chun-Yi
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Lee, Chun-Yi @ 2010-10-01 13:51 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: mjg59, carlos, linux-input, dmitry.torokhov, tiwai, trenn, jbenc,
	Lee, Chun-Yi

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 <jlee@novell.com>
---
 drivers/platform/x86/Kconfig    |    1 +
 drivers/platform/x86/acer-wmi.c |  213 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 214 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index cff7cc2..76cdf64 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -23,6 +23,7 @@ config ACER_WMI
 	depends on BACKLIGHT_CLASS_DEVICE
 	depends on SERIO_I8042
 	depends on RFKILL || RFKILL = n
+	depends on INPUT
 	select ACPI_WMI
 	---help---
 	  This is a driver for newer Acer (and Wistron) laptops. It adds
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 2badee2..79d2553 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -37,6 +37,7 @@
 #include <linux/workqueue.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/input.h>
 
 #include <acpi/acpi_drivers.h>
 
@@ -48,6 +49,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 +85,47 @@ 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,
+};
+
+struct key_entry {
+	char type;	/* See KE_* below */
+	u16 code;
+	u16 keycode;
+};
+
+enum { KE_KEY, KE_END };
+
+static 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},	/* Aracade */
+	{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 +1126,156 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
 
 static DEVICE_ATTR(interface, S_IRUGO, show_interface, NULL);
 
+static struct key_entry *acer_wmi_get_entry_by_scancode(unsigned int code)
+{
+	struct key_entry *key;
+
+	for (key = acer_wmi_keymap; key->type != KE_END; key++) {
+		if (code == key->code)
+			return key;
+	}
+
+	return NULL;
+}
+
+static struct key_entry *acer_wmi_get_entry_by_keycode(unsigned int keycode)
+{
+	struct key_entry *key;
+
+	for (key = acer_wmi_keymap; key->type != KE_END; key++)
+		if (key->type == KE_KEY && keycode == key->keycode)
+			return key;
+
+	return NULL;
+}
+
+static int acer_wmi_getkeycode(struct input_dev *dev,
+			unsigned int scancode, unsigned int *keycode)
+{
+	struct key_entry *key = acer_wmi_get_entry_by_scancode(scancode);
+
+	if (key && key->type == KE_KEY) {
+		*keycode = key->keycode;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int acer_wmi_setkeycode(struct input_dev *dev,
+			unsigned int scancode, unsigned int keycode)
+{
+	struct key_entry *key;
+	unsigned int old_keycode;
+
+	key = acer_wmi_get_entry_by_scancode(scancode);
+	if (key && key->type == KE_KEY) {
+		old_keycode = key->keycode;
+		key->keycode = keycode;
+		set_bit(keycode, dev->keybit);
+		if (!acer_wmi_get_entry_by_keycode(old_keycode))
+			clear_bit(old_keycode, dev->keybit);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static void acer_wmi_notify(u32 value, void *context)
+{
+	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
+	static struct key_entry *key;
+	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:
+		key = acer_wmi_get_entry_by_scancode(return_value.key_num);
+		if (key) {
+			switch (key->type) {
+			case KE_KEY:
+				input_report_key(acer_wmi_input_dev,
+						key->keycode, 1);
+				input_sync(acer_wmi_input_dev);
+				input_report_key(acer_wmi_input_dev,
+						key->keycode, 0);
+				input_sync(acer_wmi_input_dev);
+				break;
+			}
+		} else
+			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)
+{
+	struct key_entry *key;
+	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;
+	acer_wmi_input_dev->getkeycode = acer_wmi_getkeycode;
+	acer_wmi_input_dev->setkeycode = acer_wmi_setkeycode;
+
+	for (key = acer_wmi_keymap; key->type != KE_END; key++) {
+		switch (key->type) {
+		case KE_KEY:
+			set_bit(EV_KEY, acer_wmi_input_dev->evbit);
+			set_bit(key->keycode, acer_wmi_input_dev->keybit);
+			break;
+		}
+	}
+
+	set_bit(EV_SW, acer_wmi_input_dev->evbit);
+
+	err = input_register_device(acer_wmi_input_dev);
+
+	if (err) {
+		input_free_device(acer_wmi_input_dev);
+		return err;
+	}
+
+	return 0;
+}
+
 /*
  * debugfs functions
  */
@@ -1327,6 +1518,18 @@ static int __init acer_wmi_init(void)
 		       "generic video driver\n");
 	}
 
+	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
+		err = wmi_install_notify_handler(ACERWMID_EVENT_GUID,
+						acer_wmi_notify, NULL);
+		if (ACPI_FAILURE(err))
+			return -EINVAL;
+		err = acer_wmi_input_setup();
+		if (err) {
+			wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
+			return err;
+		}
+	}
+
 	err = platform_driver_register(&acer_platform_driver);
 	if (err) {
 		printk(ACER_ERR "Unable to register platform driver.\n");
@@ -1368,11 +1571,21 @@ error_device_add:
 error_device_alloc:
 	platform_driver_unregister(&acer_platform_driver);
 error_platform_register:
+	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
+		input_unregister_device(acer_wmi_input_dev);
+		wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
+	}
+
 	return err;
 }
 
 static void __exit acer_wmi_exit(void)
 {
+	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
+		wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
+		input_unregister_device(acer_wmi_input_dev);
+	}
+
 	remove_sysfs(acer_platform_device);
 	remove_debugfs();
 	platform_device_unregister(acer_platform_device);
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/2] Support enable Acer Launch Manager mode
  2010-10-01 13:51 [PATCH 1/2] Add acer wmi hotkey events support Lee, Chun-Yi
@ 2010-10-01 13:51 ` Lee, Chun-Yi
  2010-10-01 14:03 ` [PATCH 1/2] Add acer wmi hotkey events support Corentin Chary
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Lee, Chun-Yi @ 2010-10-01 13:51 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: mjg59, carlos, linux-input, dmitry.torokhov, tiwai, trenn, jbenc,
	Lee, Chun-Yi

Add a launch_manager parameter for support to enable Acer Launch Manager
mode. After enable it, the communication key will stop the default
behavior to control WLAN/Bluetooth/WWAN rfkill state. It leave usernland
application to handle the rfkill state changed

Signed-off-by: Lee, Chun-Yi <jlee@novell.com>
---
 drivers/platform/x86/acer-wmi.c |   73 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 73 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 79d2553..562e853 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -84,6 +84,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
@@ -127,6 +128,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
  */
@@ -157,15 +172,18 @@ static int mailled = -1;
 static int brightness = -1;
 static int threeg = -1;
 static int force_series;
+static bool launch_manager;
 
 module_param(mailled, int, 0444);
 module_param(brightness, int, 0444);
 module_param(threeg, int, 0444);
 module_param(force_series, int, 0444);
+module_param(launch_manager, 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(launch_manager, "Enable Acer Launch Manager mode");
 
 struct acer_data {
 	int mailled;
@@ -1457,6 +1475,52 @@ error_debugfs:
 	return -ENOMEM;
 }
 
+static int acer_wmi_enable_lm(void)
+{
+	struct lm_return_value return_value;
+	acpi_status status;
+	union acpi_object *obj;
+	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 */
+	};
+
+	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 -EINVAL;
+	else if (obj->type != ACPI_TYPE_BUFFER) {
+		kfree(obj);
+		return -EINVAL;
+	}
+	if (obj->buffer.length != 4) {
+		printk(ACER_WARNING "Unknown buffer length %d\n",
+			obj->buffer.length);
+		kfree(obj);
+		return -EINVAL;
+	}
+
+	return_value = *((struct lm_return_value *)obj->buffer.pointer);
+	kfree(obj);
+
+	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;
@@ -1518,6 +1582,15 @@ static int __init acer_wmi_init(void)
 		       "generic video driver\n");
 	}
 
+	if (wmi_has_guid(WMID_GUID3) && launch_manager) {
+		if (ACPI_FAILURE(acer_wmi_enable_lm())) {
+			printk(ACER_ERR "Cannot enable Launch Manager mode\n");
+			return -ENODEV;
+		}
+	} else if (!wmi_has_guid(WMID_GUID3) && launch_manager) {
+		printk(ACER_INFO "No WMID launch manager enable method found\n");
+	}
+
 	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
 		err = wmi_install_notify_handler(ACERWMID_EVENT_GUID,
 						acer_wmi_notify, NULL);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] Add acer wmi hotkey events support
  2010-10-01 13:51 [PATCH 1/2] Add acer wmi hotkey events support Lee, Chun-Yi
  2010-10-01 13:51 ` [PATCH 2/2] Support enable Acer Launch Manager mode Lee, Chun-Yi
@ 2010-10-01 14:03 ` Corentin Chary
  2010-10-01 16:58 ` Dmitry Torokhov
  2010-10-01 18:16 ` Carlos Corbacho
  3 siblings, 0 replies; 10+ messages in thread
From: Corentin Chary @ 2010-10-01 14:03 UTC (permalink / raw)
  To: Lee, Chun-Yi
  Cc: platform-driver-x86, mjg59, carlos, linux-input, dmitry.torokhov,
	tiwai, trenn, jbenc, Lee, Chun-Yi

On Fri, Oct 1, 2010 at 3:51 PM, Lee, Chun-Yi <joeyli.kernel@gmail.com> wrote:
> 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 <jlee@novell.com>

Hi Lee,
You'll probably want to take a look at the sparse keymap library. Using
it would remove a lot of code from this patch.
Thanks

-- 
Corentin Chary
http://xf.iksaif.net

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] Add acer wmi hotkey events support
  2010-10-01 13:51 [PATCH 1/2] Add acer wmi hotkey events support Lee, Chun-Yi
  2010-10-01 13:51 ` [PATCH 2/2] Support enable Acer Launch Manager mode Lee, Chun-Yi
  2010-10-01 14:03 ` [PATCH 1/2] Add acer wmi hotkey events support Corentin Chary
@ 2010-10-01 16:58 ` Dmitry Torokhov
  2010-10-01 18:16 ` Carlos Corbacho
  3 siblings, 0 replies; 10+ messages in thread
From: Dmitry Torokhov @ 2010-10-01 16:58 UTC (permalink / raw)
  To: Lee, Chun-Yi
  Cc: platform-driver-x86, mjg59, carlos, linux-input, tiwai, trenn,
	jbenc, Lee, Chun-Yi

Hi Lee,

On Fri, Oct 01, 2010 at 09:51:27PM +0800, Lee, Chun-Yi wrote:
> +
> +struct key_entry {
> +	char type;	/* See KE_* below */
> +	u16 code;
> +	u16 keycode;
> +};
> +
> +enum { KE_KEY, KE_END };
> +

Like Corentin said, please use sparse_keymap, it will cut the code in
half.

> +
> +	set_bit(EV_SW, acer_wmi_input_dev->evbit);
> +

I do not see you sending SW_* events...

> +	err = input_register_device(acer_wmi_input_dev);
> +
> +	if (err) {
> +		input_free_device(acer_wmi_input_dev);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * debugfs functions
>   */
> @@ -1327,6 +1518,18 @@ static int __init acer_wmi_init(void)
>  		       "generic video driver\n");
>  	}
>  
> +	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
> +		err = wmi_install_notify_handler(ACERWMID_EVENT_GUID,
> +						acer_wmi_notify, NULL);
> +		if (ACPI_FAILURE(err))
> +			return -EINVAL;
> +		err = acer_wmi_input_setup();

You really want to set up the device first and install notify handler
later. What will happen if event will fire up while input device has not
been created yet?

> +		if (err) {
> +			wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
> +			return err;
> +		}
> +	}
> +
>  	err = platform_driver_register(&acer_platform_driver);
>  	if (err) {
>  		printk(ACER_ERR "Unable to register platform driver.\n");
> @@ -1368,11 +1571,21 @@ error_device_add:
>  error_device_alloc:
>  	platform_driver_unregister(&acer_platform_driver);
>  error_platform_register:
> +	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
> +		input_unregister_device(acer_wmi_input_dev);
> +		wmi_remove_notify_handler(ACERWMID_EVENT_GUID);

Same here, first shut off notified, then remove the device.

> +	}
> +
>  	return err;
>  }
>  
>  static void __exit acer_wmi_exit(void)
>  {
> +	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
> +		wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
> +		input_unregister_device(acer_wmi_input_dev);

Same here.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] Add acer wmi hotkey events support
@ 2010-10-01 17:37 Joey Lee
  2010-10-01 17:44 ` Dmitry Torokhov
  0 siblings, 1 reply; 10+ messages in thread
From: Joey Lee @ 2010-10-01 17:37 UTC (permalink / raw)
  To: corentin.chary
  Cc: dmitry.torokhov, Takashi Iwai, Thomas Renninger, mjg59, carlos,
	jbenc, linux-input, platform-driver-x86

Hi Corentin, 

於 五,2010-10-01 於 16:03 +0200,Corentin Chary 提到:
> On Fri, Oct 1, 2010 at 3:51 PM, Lee, Chun-Yi <joeyli.kernel@gmail.com> wrote:
> > 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 <jlee@novell.com>
> 
> Hi Lee,
> You'll probably want to take a look at the sparse keymap library. Using
> it would remove a lot of code from this patch.
> Thanks
> 

Thank's for your suggestion, I just goolge it:
 http://www.spinics.net/lists/linux-input/msg10336.html

And, you are right, it's a very good framework for keymap handler.
I will modify patch to use sparse keymap library.

I believe it already available in newest kernel.
Does it already in 2.6.32 kernel? Because I also need backport those 2
patches to 2.6.32.x kernel.


Thank's
Joey Lee

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] Add acer wmi hotkey events support
  2010-10-01 17:37 Joey Lee
@ 2010-10-01 17:44 ` Dmitry Torokhov
  2010-10-01 17:46   ` Dmitry Torokhov
  0 siblings, 1 reply; 10+ messages in thread
From: Dmitry Torokhov @ 2010-10-01 17:44 UTC (permalink / raw)
  To: Joey Lee
  Cc: corentin.chary, Takashi Iwai, Thomas Renninger, mjg59, carlos,
	jbenc, linux-input, platform-driver-x86

On Fri, Oct 01, 2010 at 11:37:48AM -0600, Joey Lee wrote:
> Hi Corentin, 
> 
> 於 五,2010-10-01 於 16:03 +0200,Corentin Chary 提到:
> > On Fri, Oct 1, 2010 at 3:51 PM, Lee, Chun-Yi <joeyli.kernel@gmail.com> wrote:
> > > 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 <jlee@novell.com>
> > 
> > Hi Lee,
> > You'll probably want to take a look at the sparse keymap library. Using
> > it would remove a lot of code from this patch.
> > Thanks
> > 
> 
> Thank's for your suggestion, I just goolge it:
>  http://www.spinics.net/lists/linux-input/msg10336.html
> 
> And, you are right, it's a very good framework for keymap handler.
> I will modify patch to use sparse keymap library.
> 
> I believe it already available in newest kernel.
> Does it already in 2.6.32 kernel? Because I also need backport those 2
> patches to 2.6.32.x kernel.
> 

Unfortunately it is in 2.6.33 onward.

-- 
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] Add acer wmi hotkey events support
  2010-10-01 17:44 ` Dmitry Torokhov
@ 2010-10-01 17:46   ` Dmitry Torokhov
  0 siblings, 0 replies; 10+ messages in thread
From: Dmitry Torokhov @ 2010-10-01 17:46 UTC (permalink / raw)
  To: Joey Lee
  Cc: corentin.chary, Takashi Iwai, Thomas Renninger, mjg59, carlos,
	jbenc, linux-input, platform-driver-x86

On Fri, Oct 01, 2010 at 10:44:22AM -0700, Dmitry Torokhov wrote:
> On Fri, Oct 01, 2010 at 11:37:48AM -0600, Joey Lee wrote:
> > Hi Corentin, 
> > 
> > 於 五,2010-10-01 於 16:03 +0200,Corentin Chary 提到:
> > > On Fri, Oct 1, 2010 at 3:51 PM, Lee, Chun-Yi <joeyli.kernel@gmail.com> wrote:
> > > > 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 <jlee@novell.com>
> > > 
> > > Hi Lee,
> > > You'll probably want to take a look at the sparse keymap library. Using
> > > it would remove a lot of code from this patch.
> > > Thanks
> > > 
> > 
> > Thank's for your suggestion, I just goolge it:
> >  http://www.spinics.net/lists/linux-input/msg10336.html
> > 
> > And, you are right, it's a very good framework for keymap handler.
> > I will modify patch to use sparse keymap library.
> > 
> > I believe it already available in newest kernel.
> > Does it already in 2.6.32 kernel? Because I also need backport those 2
> > patches to 2.6.32.x kernel.
> > 
> 
> Unfortunately it is in 2.6.33 onward.
> 

... but you shold be able to add the module to your distibution, it is
pretty much self-contained. If you do so there were a couple of fixes in
later kernels you might want to grab as well.

-- 
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] Add acer wmi hotkey events support
  2010-10-01 13:51 [PATCH 1/2] Add acer wmi hotkey events support Lee, Chun-Yi
                   ` (2 preceding siblings ...)
  2010-10-01 16:58 ` Dmitry Torokhov
@ 2010-10-01 18:16 ` Carlos Corbacho
  3 siblings, 0 replies; 10+ messages in thread
From: Carlos Corbacho @ 2010-10-01 18:16 UTC (permalink / raw)
  To: Lee, Chun-Yi
  Cc: platform-driver-x86, mjg59, linux-input, dmitry.torokhov, tiwai,
	trenn, jbenc, Lee, Chun-Yi

On Friday 01 October 2010 14:51:27 Lee, Chun-Yi wrote:
> 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.

What hardware is this for? Up to now, all Acer hardware I'm aware of has 
always sent key codes. This and the other patch seem to be for something 
that's quite different to the current batch of hardware supported by acer-wmi?

-Carlos
-- 
E-Mail: carlos@strangeworlds.co.uk
Web: strangeworlds.co.uk
GPG Key ID: 0x23EE722D

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] Add acer wmi hotkey events support
@ 2010-10-01 19:20 Joey Lee
  0 siblings, 0 replies; 10+ messages in thread
From: Joey Lee @ 2010-10-01 19:20 UTC (permalink / raw)
  To: carlos
  Cc: dmitry.torokhov, Takashi Iwai, Thomas Renninger, mjg59, jbenc,
	linux-input, platform-driver-x86

Hi Carlos, 

於 五,2010-10-01 於 19:16 +0100,Carlos Corbacho 提到:
> On Friday 01 October 2010 14:51:27 Lee, Chun-Yi wrote:
> > 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.
> 
> What hardware is this for? Up to now, all Acer hardware I'm aware of has 
> always sent key codes. This and the other patch seem to be for something 
> that's quite different to the current batch of hardware supported by acer-wmi?
> 

The hardware is Acer TravelMate 8572, the machine send out key code:
volume up/down, mute, brightness up/down 
So, the above hotkeys work fine.

But, it send out wmi event for: 
wifi key (the same with communication key), P key (a special program
key), touchpad, video mode switch. 

My patch work for translate those wmi event to key code.


Thank's
Joey Lee

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] Add acer wmi hotkey events support
@ 2010-10-12  1:56 Joey Lee
  0 siblings, 0 replies; 10+ messages in thread
From: Joey Lee @ 2010-10-12  1:56 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: Takashi Iwai, Thomas Renninger, mjg59, carlos, jbenc, linux-input,
	platform-driver-x86

[-- Attachment #1: Type: text/plain, Size: 12966 bytes --]

Hi Dmitry,

於 五,2010-10-01 於 09:58 -0700,Dmitry Torokhov 提到:
> Hi Lee,
> 
> On Fri, Oct 01, 2010 at 09:51:27PM +0800, Lee, Chun-Yi wrote:
> > +
> > +struct key_entry {
> > +	char type;	/* See KE_* below */
> > +	u16 code;
> > +	u16 keycode;
> > +};
> > +
> > +enum { KE_KEY, KE_END };
> > +
> 
> Like Corentin said, please use sparse_keymap, it will cut the code in
> half.
> 

Thank's for your and Corentin's suggestion, I already used sparse keymap
framework.

> > +
> > +	set_bit(EV_SW, acer_wmi_input_dev->evbit);
> > +
> 
> I do not see you sending SW_* events...
> 
> > +	err = input_register_device(acer_wmi_input_dev);
> > +
> > +	if (err) {
> > +		input_free_device(acer_wmi_input_dev);
> > +		return err;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  /*
> >   * debugfs functions
> >   */
> > @@ -1327,6 +1518,18 @@ static int __init acer_wmi_init(void)
> >  		       "generic video driver\n");
> >  	}
> >  
> > +	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
> > +		err = wmi_install_notify_handler(ACERWMID_EVENT_GUID,
> > +						acer_wmi_notify, NULL);
> > +		if (ACPI_FAILURE(err))
> > +			return -EINVAL;
> > +		err = acer_wmi_input_setup();
> 
> You really want to set up the device first and install notify handler
> later. What will happen if event will fire up while input device has not
> been created yet?
> 
> > +		if (err) {
> > +			wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
> > +			return err;
> > +		}
> > +	}
> > +
> >  	err = platform_driver_register(&acer_platform_driver);
> >  	if (err) {
> >  		printk(ACER_ERR "Unable to register platform driver.\n");
> > @@ -1368,11 +1571,21 @@ error_device_add:
> >  error_device_alloc:
> >  	platform_driver_unregister(&acer_platform_driver);
> >  error_platform_register:
> > +	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
> > +		input_unregister_device(acer_wmi_input_dev);
> > +		wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
> 
> Same here, first shut off notified, then remove the device.
> 
> > +	}
> > +
> >  	return err;
> >  }
> >  
> >  static void __exit acer_wmi_exit(void)
> >  {
> > +	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
> > +		wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
> > +		input_unregister_device(acer_wmi_input_dev);
> 
> Same here.
> 
> Thanks.
> 

Thank's for your review, I modified 2 patches like the following. I also
attached those 2 patches on this mail.

Thank's a lot
Joey Lee

>From 0e6f011a9a2219a47c93aa68433ba457ae1068e5 Mon Sep 17 00:00:00 2001
From: Lee, Chun-Yi <jlee@novell.com>
Date: Tue, 12 Oct 2010 09:26:29 +0800
Subject: [PATCH 1/2] Add acer wmi hotkey events support

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 <jlee@novell.com>
---
 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..32285f4 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} },    /* Aracade */
+	{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;
+
+	err = input_register_device(acer_wmi_input_dev);
+	if (err)
+		goto err_free_keymap;
+
+	status = wmi_install_notify_handler(ACERWMID_EVENT_GUID,
+						acer_wmi_notify, NULL);
+	if (ACPI_FAILURE(status)) {
+		err = -EIO;
+		goto err_unregister_input;
+	}
+
+	return 0;
+
+err_unregister_input:
+	input_unregister_device(acer_wmi_input_dev);
+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

>From 1957b6b7cd071de95c0e1fb0e35cd5c9c9332630 Mon Sep 17 00:00:00 2001
From: Lee, Chun-Yi <jlee@novell.com>
Date: Tue, 12 Oct 2010 09:27:23 +0800
Subject: [PATCH 2/2] Support enable Acer Launch Manager mode

Add a launch_manager parameter for support to enable Acer Launch Manager
mode. After enable it, the communication key will stop the default
behavior to control WLAN/Bluetooth/WWAN rfkill state. It leave usernland
application to handle the rfkill state changed.

Signed-off-by: Lee, Chun-Yi <jlee@novell.com>
---
 drivers/platform/x86/acer-wmi.c |   74
+++++++++++++++++++++++++++++++++++++++
 1 files changed, 74 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/x86/acer-wmi.c
b/drivers/platform/x86/acer-wmi.c
index 32285f4..a28a775 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 launch_manager;
 
 module_param(mailled, int, 0444);
 module_param(brightness, int, 0444);
 module_param(threeg, int, 0444);
 module_param(force_series, int, 0444);
+module_param(launch_manager, 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(launch_manager, "Enable Acer Launch Manager mode");
 
 struct acer_data {
 	int mailled;
@@ -1393,6 +1411,53 @@ error_debugfs:
 	return -ENOMEM;
 }
 
+static int acer_wmi_enable_lm(void)
+{
+	struct lm_return_value return_value;
+	acpi_status status;
+	union acpi_object *obj;
+	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 */
+	};
+
+	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 -EINVAL;
+	else if (obj->type != ACPI_TYPE_BUFFER) {
+		kfree(obj);
+		return -EINVAL;
+	}
+	if (obj->buffer.length != 4) {
+		printk(ACER_WARNING "Unknown buffer length %d\n",
+			obj->buffer.length);
+		kfree(obj);
+		return -EINVAL;
+	}
+
+	return_value = *((struct lm_return_value *)obj->buffer.pointer);
+	kfree(obj);
+
+	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 +1519,15 @@ static int __init acer_wmi_init(void)
 		       "generic video driver\n");
 	}
 
+	if (wmi_has_guid(WMID_GUID3) && launch_manager) {
+		if (ACPI_FAILURE(acer_wmi_enable_lm())) {
+			printk(ACER_ERR "Cannot enable Launch Manager mode\n");
+			return -ENODEV;
+		}
+	} else if (!wmi_has_guid(WMID_GUID3) && launch_manager) {
+		printk(ACER_INFO "No WMID launch manager enable method\n");
+	}
+
 	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
 		err = acer_wmi_input_setup();
 		if (err)
-- 
1.6.0.2






[-- Attachment #2: 0001-Add-acer-wmi-hotkey-events-support.PATCH --]
[-- Type: text/plain, Size: 6480 bytes --]

>From 0e6f011a9a2219a47c93aa68433ba457ae1068e5 Mon Sep 17 00:00:00 2001
From: Lee, Chun-Yi <jlee@novell.com>
Date: Tue, 12 Oct 2010 09:26:29 +0800
Subject: [PATCH 1/2] Add acer wmi hotkey events support

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 <jlee@novell.com>
---
 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..32285f4 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} },    /* Aracade */
+	{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;
+
+	err = input_register_device(acer_wmi_input_dev);
+	if (err)
+		goto err_free_keymap;
+
+	status = wmi_install_notify_handler(ACERWMID_EVENT_GUID,
+						acer_wmi_notify, NULL);
+	if (ACPI_FAILURE(status)) {
+		err = -EIO;
+		goto err_unregister_input;
+	}
+
+	return 0;
+
+err_unregister_input:
+	input_unregister_device(acer_wmi_input_dev);
+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


[-- Attachment #3: 0002-Support-enable-Acer-Launch-Manager-mode.PATCH --]
[-- Type: text/plain, Size: 4442 bytes --]

>From 1957b6b7cd071de95c0e1fb0e35cd5c9c9332630 Mon Sep 17 00:00:00 2001
From: Lee, Chun-Yi <jlee@novell.com>
Date: Tue, 12 Oct 2010 09:27:23 +0800
Subject: [PATCH 2/2] Support enable Acer Launch Manager mode

Add a launch_manager parameter for support to enable Acer Launch Manager
mode. After enable it, the communication key will stop the default
behavior to control WLAN/Bluetooth/WWAN rfkill state. It leave usernland
application to handle the rfkill state changed.

Signed-off-by: Lee, Chun-Yi <jlee@novell.com>
---
 drivers/platform/x86/acer-wmi.c |   74 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 74 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 32285f4..a28a775 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 launch_manager;
 
 module_param(mailled, int, 0444);
 module_param(brightness, int, 0444);
 module_param(threeg, int, 0444);
 module_param(force_series, int, 0444);
+module_param(launch_manager, 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(launch_manager, "Enable Acer Launch Manager mode");
 
 struct acer_data {
 	int mailled;
@@ -1393,6 +1411,53 @@ error_debugfs:
 	return -ENOMEM;
 }
 
+static int acer_wmi_enable_lm(void)
+{
+	struct lm_return_value return_value;
+	acpi_status status;
+	union acpi_object *obj;
+	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 */
+	};
+
+	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 -EINVAL;
+	else if (obj->type != ACPI_TYPE_BUFFER) {
+		kfree(obj);
+		return -EINVAL;
+	}
+	if (obj->buffer.length != 4) {
+		printk(ACER_WARNING "Unknown buffer length %d\n",
+			obj->buffer.length);
+		kfree(obj);
+		return -EINVAL;
+	}
+
+	return_value = *((struct lm_return_value *)obj->buffer.pointer);
+	kfree(obj);
+
+	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 +1519,15 @@ static int __init acer_wmi_init(void)
 		       "generic video driver\n");
 	}
 
+	if (wmi_has_guid(WMID_GUID3) && launch_manager) {
+		if (ACPI_FAILURE(acer_wmi_enable_lm())) {
+			printk(ACER_ERR "Cannot enable Launch Manager mode\n");
+			return -ENODEV;
+		}
+	} else if (!wmi_has_guid(WMID_GUID3) && launch_manager) {
+		printk(ACER_INFO "No WMID launch manager enable method\n");
+	}
+
 	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
 		err = acer_wmi_input_setup();
 		if (err)
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2010-10-12  1:56 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-01 13:51 [PATCH 1/2] Add acer wmi hotkey events support Lee, Chun-Yi
2010-10-01 13:51 ` [PATCH 2/2] Support enable Acer Launch Manager mode Lee, Chun-Yi
2010-10-01 14:03 ` [PATCH 1/2] Add acer wmi hotkey events support Corentin Chary
2010-10-01 16:58 ` Dmitry Torokhov
2010-10-01 18:16 ` Carlos Corbacho
  -- strict thread matches above, loose matches on Subject: below --
2010-10-01 17:37 Joey Lee
2010-10-01 17:44 ` Dmitry Torokhov
2010-10-01 17:46   ` Dmitry Torokhov
2010-10-01 19:20 Joey Lee
2010-10-12  1:56 Joey Lee

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).