All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] asus-wmi: record wlan status while controlled by userapp
@ 2012-07-26  3:33 AceLan Kao
  2012-07-26  3:34 ` [PATCH 2/2] asus-wmi: update wlan LED through rfkill led trigger AceLan Kao
  2012-07-26  5:22 ` [PATCH 1/2] asus-wmi: record wlan status while controlled by userapp Corentin Chary
  0 siblings, 2 replies; 11+ messages in thread
From: AceLan Kao @ 2012-07-26  3:33 UTC (permalink / raw)
  To: platform-driver-x86, Corentin Chary

If the user bit is set, that mean BIOS can't set and record the wlan
status, it will report the value read from id ASUS_WMI_DEVID_WLAN_LED
(0x00010012) while we query the wlan status by id ASUS_WMI_DEVID_WLAN
(0x00010011) through WMI.
So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED
(0x00010012) while setting the wlan status through WMI.
This is also the behavior that windows app will do.

Quote from ASUS application engineer
===
When you call WMIMethod(DSTS, 0x00010011) to get WLAN status, it may return

(1) 0x00050001 (On)
(2) 0x00050000 (Off)
(3) 0x00030001 (On)
(4) 0x00030000 (Off)
(5) 0x00000002 (Unknown)

(1), (2) means that the model has hardware GPIO for WLAN, you can call
WMIMethod(DEVS, 0x00010011, 1 or 0) to turn WLAN on/off.
(3), (4) means that the model doesn’t have hardware GPIO, you need to use
API or driver library to turn WLAN on/off, and call
WMIMethod(DEVS, 0x00010012, 1 or 0) to set WLAN LED status.
After you set WLAN LED status, you can see the WLAN status is changed with
WMIMethod(DSTS, 0x00010011). Because the status is recorded lastly
(ex: Windows), you can use it for synchronization.
(5) means that the model doesn’t have WLAN device.

WLAN is the ONLY special case with upper rule.

For other device, like Bluetooth, you just need use
WMIMethod(DSTS, 0x00010013) to get, and WMIMethod(DEVS, 0x00010013, 1 or 0)
to set.
===

Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
---
 drivers/platform/x86/asus-wmi.c |   23 ++++++++++++++++++++++-
 drivers/platform/x86/asus-wmi.h |    1 +
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 77aadde..a13eb45 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -98,6 +98,7 @@ MODULE_LICENSE("GPL");
 #define ASUS_WMI_DEVID_WIRELESS_LED	0x00010002
 #define ASUS_WMI_DEVID_CWAP		0x00010003
 #define ASUS_WMI_DEVID_WLAN		0x00010011
+#define ASUS_WMI_DEVID_WLAN_LED		0x00010012
 #define ASUS_WMI_DEVID_BLUETOOTH	0x00010013
 #define ASUS_WMI_DEVID_GPS		0x00010015
 #define ASUS_WMI_DEVID_WIMAX		0x00010017
@@ -493,6 +494,8 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
 
 		rv = led_classdev_register(&asus->platform_device->dev,
 					   &asus->kbd_led);
+		if (rv)
+			goto error;
 	}
 
 error:
@@ -725,8 +728,21 @@ static int asus_rfkill_set(void *data, bool blocked)
 {
 	struct asus_rfkill *priv = data;
 	u32 ctrl_param = !blocked;
+	u32 dev_id = priv->dev_id;
+
+	/*
+	 * If the user bit is set, BIOS can't set and record the wlan status,
+	 * it will report the value read from id ASUS_WMI_DEVID_WLAN_LED
+	 * while we query the wlan status through WMI(ASUS_WMI_DEVID_WLAN).
+	 * So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED
+	 * while setting the wlan status through WMI.
+	 * This is also the behavior that windows app will do.
+	 */
+	if ((dev_id == ASUS_WMI_DEVID_WLAN) &&
+	     priv->asus->driver->wlan_ctrl_by_user)
+		dev_id = ASUS_WMI_DEVID_WLAN_LED;
 
-	return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL);
+	return asus_wmi_set_devstate(dev_id, ctrl_param, NULL);
 }
 
 static void asus_rfkill_query(struct rfkill *rfkill, void *data)
@@ -1648,6 +1664,7 @@ static int asus_wmi_add(struct platform_device *pdev)
 	struct asus_wmi *asus;
 	acpi_status status;
 	int err;
+	u32 result;
 
 	asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL);
 	if (!asus)
@@ -1700,6 +1717,10 @@ static int asus_wmi_add(struct platform_device *pdev)
 	if (err)
 		goto fail_debugfs;
 
+	asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result);
+	if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT))
+		asus->driver->wlan_ctrl_by_user = 1;
+
 	return 0;
 
 fail_debugfs:
diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h
index d43b667..cbe7ee2 100644
--- a/drivers/platform/x86/asus-wmi.h
+++ b/drivers/platform/x86/asus-wmi.h
@@ -45,6 +45,7 @@ struct quirk_entry {
 struct asus_wmi_driver {
 	int			brightness;
 	int			panel_power;
+	int			wlan_ctrl_by_user;
 
 	const char		*name;
 	struct module		*owner;
-- 
1.7.9.5

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

* [PATCH 2/2] asus-wmi: update wlan LED through rfkill led trigger
  2012-07-26  3:33 [PATCH 1/2] asus-wmi: record wlan status while controlled by userapp AceLan Kao
@ 2012-07-26  3:34 ` AceLan Kao
  2012-07-26  3:39   ` AceLan Kao
  2012-07-26  5:19   ` Corentin Chary
  2012-07-26  5:22 ` [PATCH 1/2] asus-wmi: record wlan status while controlled by userapp Corentin Chary
  1 sibling, 2 replies; 11+ messages in thread
From: AceLan Kao @ 2012-07-26  3:34 UTC (permalink / raw)
  To: platform-driver-x86, Corentin Chary

For those machines with wapf=4, BIOS won't update the wireless LED,
since wapf=4 means user application will take in chage of the wifi and bt.
So, we have to update wlan LED status explicitly.

But I found there is another wireless LED bug in launchpad and which is
not in the wapf=4 quirk.
So, it might be better to set wireless LED status explicitly for all
machines.

BugLink: https://launchpad.net/bugs/901105

Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
---
 drivers/platform/x86/asus-wmi.c |   24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index a13eb45..6ddfb0b 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -183,6 +183,7 @@ struct asus_wmi {
 	struct device *hwmon_device;
 	struct platform_device *platform_device;
 
+	struct led_classdev wlan_led;
 	struct led_classdev tpd_led;
 	int tpd_led_wk;
 	struct led_classdev kbd_led;
@@ -452,12 +453,20 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
 	return value;
 }
 
+static void wlan_led_set(struct led_classdev *led_cdev,
+			 enum led_brightness value)
+{
+	asus_wmi_set_devstate(ASUS_WMI_DEVID_WIRELESS_LED, value, NULL);
+}
+
 static void asus_wmi_led_exit(struct asus_wmi *asus)
 {
 	if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
 		led_classdev_unregister(&asus->kbd_led);
 	if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
 		led_classdev_unregister(&asus->tpd_led);
+	if (!IS_ERR_OR_NULL(asus->wlan_led.dev))
+		led_classdev_unregister(&asus->wlan_led);
 	if (asus->led_workqueue)
 		destroy_workqueue(asus->led_workqueue);
 }
@@ -465,6 +474,7 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
 static int asus_wmi_led_init(struct asus_wmi *asus)
 {
 	int rv = 0;
+	u32 result;
 
 	asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
 	if (!asus->led_workqueue)
@@ -498,6 +508,17 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
 			goto error;
 	}
 
+	asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
+	if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
+		asus->wlan_led.name = "asus-wmi::wlan";
+		asus->wlan_led.brightness_set = wlan_led_set;
+		asus->wlan_led.flags = LED_CORE_SUSPENDRESUME;
+		asus->wlan_led.max_brightness = 1;
+		asus->wlan_led.default_trigger = "asus-wlan";
+		rv = led_classdev_register(&asus->platform_device->dev,
+					   &asus->wlan_led);
+
+	}
 error:
 	if (rv)
 		asus_wmi_led_exit(asus);
@@ -811,6 +832,9 @@ static int asus_new_rfkill(struct asus_wmi *asus,
 	if (!*rfkill)
 		return -EINVAL;
 
+	if (dev_id == ASUS_WMI_DEVID_WLAN)
+		rfkill_set_led_trigger_name(*rfkill, "asus-wlan");
+
 	rfkill_init_sw_state(*rfkill, !result);
 	result = rfkill_register(*rfkill);
 	if (result) {
-- 
1.7.9.5

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

* Re: [PATCH 2/2] asus-wmi: update wlan LED through rfkill led trigger
  2012-07-26  3:34 ` [PATCH 2/2] asus-wmi: update wlan LED through rfkill led trigger AceLan Kao
@ 2012-07-26  3:39   ` AceLan Kao
  2012-07-26  5:19   ` Corentin Chary
  1 sibling, 0 replies; 11+ messages in thread
From: AceLan Kao @ 2012-07-26  3:39 UTC (permalink / raw)
  To: platform-driver-x86, Corentin Chary

Hi,

This patch uses a function, rfkill_set_led_trigger_name(), which was
removed by commit
2e48928d8a0f38c1b5c81eb3f1294de8a6382c68
This function is necessary and should not be removed.
So, I submitted another patch to revert it to linux-wireless mailing list.
Without that revert patch, the code won't get compiled

Best regards,
AceLan Kao.

2012/7/26 AceLan Kao <acelan.kao@canonical.com>:
> For those machines with wapf=4, BIOS won't update the wireless LED,
> since wapf=4 means user application will take in chage of the wifi and bt.
> So, we have to update wlan LED status explicitly.
>
> But I found there is another wireless LED bug in launchpad and which is
> not in the wapf=4 quirk.
> So, it might be better to set wireless LED status explicitly for all
> machines.
>
> BugLink: https://launchpad.net/bugs/901105
>
> Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
> ---
>  drivers/platform/x86/asus-wmi.c |   24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> index a13eb45..6ddfb0b 100644
> --- a/drivers/platform/x86/asus-wmi.c
> +++ b/drivers/platform/x86/asus-wmi.c
> @@ -183,6 +183,7 @@ struct asus_wmi {
>         struct device *hwmon_device;
>         struct platform_device *platform_device;
>
> +       struct led_classdev wlan_led;
>         struct led_classdev tpd_led;
>         int tpd_led_wk;
>         struct led_classdev kbd_led;
> @@ -452,12 +453,20 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
>         return value;
>  }
>
> +static void wlan_led_set(struct led_classdev *led_cdev,
> +                        enum led_brightness value)
> +{
> +       asus_wmi_set_devstate(ASUS_WMI_DEVID_WIRELESS_LED, value, NULL);
> +}
> +
>  static void asus_wmi_led_exit(struct asus_wmi *asus)
>  {
>         if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
>                 led_classdev_unregister(&asus->kbd_led);
>         if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
>                 led_classdev_unregister(&asus->tpd_led);
> +       if (!IS_ERR_OR_NULL(asus->wlan_led.dev))
> +               led_classdev_unregister(&asus->wlan_led);
>         if (asus->led_workqueue)
>                 destroy_workqueue(asus->led_workqueue);
>  }
> @@ -465,6 +474,7 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
>  static int asus_wmi_led_init(struct asus_wmi *asus)
>  {
>         int rv = 0;
> +       u32 result;
>
>         asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
>         if (!asus->led_workqueue)
> @@ -498,6 +508,17 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
>                         goto error;
>         }
>
> +       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
> +       if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
> +               asus->wlan_led.name = "asus-wmi::wlan";
> +               asus->wlan_led.brightness_set = wlan_led_set;
> +               asus->wlan_led.flags = LED_CORE_SUSPENDRESUME;
> +               asus->wlan_led.max_brightness = 1;
> +               asus->wlan_led.default_trigger = "asus-wlan";
> +               rv = led_classdev_register(&asus->platform_device->dev,
> +                                          &asus->wlan_led);
> +
> +       }
>  error:
>         if (rv)
>                 asus_wmi_led_exit(asus);
> @@ -811,6 +832,9 @@ static int asus_new_rfkill(struct asus_wmi *asus,
>         if (!*rfkill)
>                 return -EINVAL;
>
> +       if (dev_id == ASUS_WMI_DEVID_WLAN)
> +               rfkill_set_led_trigger_name(*rfkill, "asus-wlan");
> +
>         rfkill_init_sw_state(*rfkill, !result);
>         result = rfkill_register(*rfkill);
>         if (result) {
> --
> 1.7.9.5
>



-- 
Chia-Lin Kao(AceLan)
http://blog.acelan.idv.tw/
E-Mail: acelan.kaoATcanonical.com (s/AT/@/)

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

* Re: [PATCH 2/2] asus-wmi: update wlan LED through rfkill led trigger
  2012-07-26  3:34 ` [PATCH 2/2] asus-wmi: update wlan LED through rfkill led trigger AceLan Kao
  2012-07-26  3:39   ` AceLan Kao
@ 2012-07-26  5:19   ` Corentin Chary
  2012-07-26  8:12     ` AceLan Kao
  1 sibling, 1 reply; 11+ messages in thread
From: Corentin Chary @ 2012-07-26  5:19 UTC (permalink / raw)
  To: AceLan Kao; +Cc: platform-driver-x86

On Thu, Jul 26, 2012 at 5:34 AM, AceLan Kao <acelan.kao@canonical.com> wrote:
> For those machines with wapf=4, BIOS won't update the wireless LED,
> since wapf=4 means user application will take in chage of the wifi and bt.
> So, we have to update wlan LED status explicitly.
>
> But I found there is another wireless LED bug in launchpad and which is
> not in the wapf=4 quirk.
> So, it might be better to set wireless LED status explicitly for all
> machines.
>
> BugLink: https://launchpad.net/bugs/901105
>
> Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
> ---
>  drivers/platform/x86/asus-wmi.c |   24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> index a13eb45..6ddfb0b 100644
> --- a/drivers/platform/x86/asus-wmi.c
> +++ b/drivers/platform/x86/asus-wmi.c
> @@ -183,6 +183,7 @@ struct asus_wmi {
>         struct device *hwmon_device;
>         struct platform_device *platform_device;
>
> +       struct led_classdev wlan_led;
>         struct led_classdev tpd_led;
>         int tpd_led_wk;
>         struct led_classdev kbd_led;
> @@ -452,12 +453,20 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
>         return value;
>  }
>
> +static void wlan_led_set(struct led_classdev *led_cdev,
> +                        enum led_brightness value)
> +{
> +       asus_wmi_set_devstate(ASUS_WMI_DEVID_WIRELESS_LED, value, NULL);
> +}
> +
>  static void asus_wmi_led_exit(struct asus_wmi *asus)
>  {
>         if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
>                 led_classdev_unregister(&asus->kbd_led);
>         if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
>                 led_classdev_unregister(&asus->tpd_led);
> +       if (!IS_ERR_OR_NULL(asus->wlan_led.dev))
> +               led_classdev_unregister(&asus->wlan_led);
>         if (asus->led_workqueue)
>                 destroy_workqueue(asus->led_workqueue);
>  }
> @@ -465,6 +474,7 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
>  static int asus_wmi_led_init(struct asus_wmi *asus)
>  {
>         int rv = 0;
> +       u32 result;
>
>         asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
>         if (!asus->led_workqueue)
> @@ -498,6 +508,17 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
>                         goto error;
>         }
>
> +       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
> +       if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
> +               asus->wlan_led.name = "asus-wmi::wlan";
> +               asus->wlan_led.brightness_set = wlan_led_set;

Why no brightness_get ?
(note that if you decide to add wl_led_get() function that returns
-ENODEV when not found (like for touchpad), please use directly
instead of checking devstate above).

> +               asus->wlan_led.flags = LED_CORE_SUSPENDRESUME;
> +               asus->wlan_led.max_brightness = 1;
> +               asus->wlan_led.default_trigger = "asus-wlan";
> +               rv = led_classdev_register(&asus->platform_device->dev,
> +                                          &asus->wlan_led);
> +
> +       }
>  error:
>         if (rv)
>                 asus_wmi_led_exit(asus);
> @@ -811,6 +832,9 @@ static int asus_new_rfkill(struct asus_wmi *asus,
>         if (!*rfkill)
>                 return -EINVAL;
>
> +       if (dev_id == ASUS_WMI_DEVID_WLAN)
> +               rfkill_set_led_trigger_name(*rfkill, "asus-wlan");
> +

I think this is only needed because leds are created before rfkill
switchs. You may also simply move rfkill_init() above led_init() (take
care of fail_led, fail_rfkill too).

Another solution is to call led_trigger_set_default() instead of
rfkill_set_led_trigger_name()

>         rfkill_init_sw_state(*rfkill, !result);
>         result = rfkill_register(*rfkill);
>         if (result) {
> --
> 1.7.9.5
>



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

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

* Re: [PATCH 1/2] asus-wmi: record wlan status while controlled by userapp
  2012-07-26  3:33 [PATCH 1/2] asus-wmi: record wlan status while controlled by userapp AceLan Kao
  2012-07-26  3:34 ` [PATCH 2/2] asus-wmi: update wlan LED through rfkill led trigger AceLan Kao
@ 2012-07-26  5:22 ` Corentin Chary
  1 sibling, 0 replies; 11+ messages in thread
From: Corentin Chary @ 2012-07-26  5:22 UTC (permalink / raw)
  To: AceLan Kao; +Cc: platform-driver-x86

On Thu, Jul 26, 2012 at 5:33 AM, AceLan Kao <acelan.kao@canonical.com> wrote:
> If the user bit is set, that mean BIOS can't set and record the wlan
> status, it will report the value read from id ASUS_WMI_DEVID_WLAN_LED
> (0x00010012) while we query the wlan status by id ASUS_WMI_DEVID_WLAN
> (0x00010011) through WMI.
> So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED
> (0x00010012) while setting the wlan status through WMI.
> This is also the behavior that windows app will do.
>
> Quote from ASUS application engineer
> ===
> When you call WMIMethod(DSTS, 0x00010011) to get WLAN status, it may return
>
> (1) 0x00050001 (On)
> (2) 0x00050000 (Off)
> (3) 0x00030001 (On)
> (4) 0x00030000 (Off)
> (5) 0x00000002 (Unknown)
>
> (1), (2) means that the model has hardware GPIO for WLAN, you can call
> WMIMethod(DEVS, 0x00010011, 1 or 0) to turn WLAN on/off.
> (3), (4) means that the model doesn’t have hardware GPIO, you need to use
> API or driver library to turn WLAN on/off, and call
> WMIMethod(DEVS, 0x00010012, 1 or 0) to set WLAN LED status.
> After you set WLAN LED status, you can see the WLAN status is changed with
> WMIMethod(DSTS, 0x00010011). Because the status is recorded lastly
> (ex: Windows), you can use it for synchronization.
> (5) means that the model doesn’t have WLAN device.
>
> WLAN is the ONLY special case with upper rule.
>
> For other device, like Bluetooth, you just need use
> WMIMethod(DSTS, 0x00010013) to get, and WMIMethod(DEVS, 0x00010013, 1 or 0)
> to set.
> ===
>
> Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
> ---
>  drivers/platform/x86/asus-wmi.c |   23 ++++++++++++++++++++++-
>  drivers/platform/x86/asus-wmi.h |    1 +
>  2 files changed, 23 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> index 77aadde..a13eb45 100644
> --- a/drivers/platform/x86/asus-wmi.c
> +++ b/drivers/platform/x86/asus-wmi.c
> @@ -98,6 +98,7 @@ MODULE_LICENSE("GPL");
>  #define ASUS_WMI_DEVID_WIRELESS_LED    0x00010002
>  #define ASUS_WMI_DEVID_CWAP            0x00010003
>  #define ASUS_WMI_DEVID_WLAN            0x00010011
> +#define ASUS_WMI_DEVID_WLAN_LED                0x00010012
>  #define ASUS_WMI_DEVID_BLUETOOTH       0x00010013
>  #define ASUS_WMI_DEVID_GPS             0x00010015
>  #define ASUS_WMI_DEVID_WIMAX           0x00010017
> @@ -493,6 +494,8 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
>
>                 rv = led_classdev_register(&asus->platform_device->dev,
>                                            &asus->kbd_led);
> +               if (rv)
> +                       goto error;
>         }
>

Hm ? Is that missing from the led patch ?

>  error:
> @@ -725,8 +728,21 @@ static int asus_rfkill_set(void *data, bool blocked)
>  {
>         struct asus_rfkill *priv = data;
>         u32 ctrl_param = !blocked;
> +       u32 dev_id = priv->dev_id;
> +
> +       /*
> +        * If the user bit is set, BIOS can't set and record the wlan status,
> +        * it will report the value read from id ASUS_WMI_DEVID_WLAN_LED
> +        * while we query the wlan status through WMI(ASUS_WMI_DEVID_WLAN).
> +        * So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED
> +        * while setting the wlan status through WMI.
> +        * This is also the behavior that windows app will do.
> +        */
> +       if ((dev_id == ASUS_WMI_DEVID_WLAN) &&
> +            priv->asus->driver->wlan_ctrl_by_user)
> +               dev_id = ASUS_WMI_DEVID_WLAN_LED;
>
> -       return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL);
> +       return asus_wmi_set_devstate(dev_id, ctrl_param, NULL);
>  }
>
>  static void asus_rfkill_query(struct rfkill *rfkill, void *data)
> @@ -1648,6 +1664,7 @@ static int asus_wmi_add(struct platform_device *pdev)
>         struct asus_wmi *asus;
>         acpi_status status;
>         int err;
> +       u32 result;
>
>         asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL);
>         if (!asus)
> @@ -1700,6 +1717,10 @@ static int asus_wmi_add(struct platform_device *pdev)
>         if (err)
>                 goto fail_debugfs;
>
> +       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result);
> +       if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT))
> +               asus->driver->wlan_ctrl_by_user = 1;
> +
>         return 0;
>
>  fail_debugfs:
> diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h
> index d43b667..cbe7ee2 100644
> --- a/drivers/platform/x86/asus-wmi.h
> +++ b/drivers/platform/x86/asus-wmi.h
> @@ -45,6 +45,7 @@ struct quirk_entry {
>  struct asus_wmi_driver {
>         int                     brightness;
>         int                     panel_power;
> +       int                     wlan_ctrl_by_user;
>
>         const char              *name;
>         struct module           *owner;
> --
> 1.7.9.5
>

Except the led artifact, this patch look ok. Please fix the led patch
and we should be done !
Thanks !

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

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

* Re: [PATCH 2/2] asus-wmi: update wlan LED through rfkill led trigger
  2012-07-26  5:19   ` Corentin Chary
@ 2012-07-26  8:12     ` AceLan Kao
  2012-07-26 12:11       ` Corentin Chary
  0 siblings, 1 reply; 11+ messages in thread
From: AceLan Kao @ 2012-07-26  8:12 UTC (permalink / raw)
  To: Corentin Chary; +Cc: platform-driver-x86

Dear Corentin,

2012/7/26 Corentin Chary <corentincj@iksaif.net>:
> On Thu, Jul 26, 2012 at 5:34 AM, AceLan Kao <acelan.kao@canonical.com> wrote:
>> For those machines with wapf=4, BIOS won't update the wireless LED,
>> since wapf=4 means user application will take in chage of the wifi and bt.
>> So, we have to update wlan LED status explicitly.
>>
>> But I found there is another wireless LED bug in launchpad and which is
>> not in the wapf=4 quirk.
>> So, it might be better to set wireless LED status explicitly for all
>> machines.
>>
>> BugLink: https://launchpad.net/bugs/901105
>>
>> Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
>> ---
>>  drivers/platform/x86/asus-wmi.c |   24 ++++++++++++++++++++++++
>>  1 file changed, 24 insertions(+)
>>
>> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
>> index a13eb45..6ddfb0b 100644
>> --- a/drivers/platform/x86/asus-wmi.c
>> +++ b/drivers/platform/x86/asus-wmi.c
>> @@ -183,6 +183,7 @@ struct asus_wmi {
>>         struct device *hwmon_device;
>>         struct platform_device *platform_device;
>>
>> +       struct led_classdev wlan_led;
>>         struct led_classdev tpd_led;
>>         int tpd_led_wk;
>>         struct led_classdev kbd_led;
>> @@ -452,12 +453,20 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
>>         return value;
>>  }
>>
>> +static void wlan_led_set(struct led_classdev *led_cdev,
>> +                        enum led_brightness value)
>> +{
>> +       asus_wmi_set_devstate(ASUS_WMI_DEVID_WIRELESS_LED, value, NULL);
>> +}
>> +
>>  static void asus_wmi_led_exit(struct asus_wmi *asus)
>>  {
>>         if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
>>                 led_classdev_unregister(&asus->kbd_led);
>>         if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
>>                 led_classdev_unregister(&asus->tpd_led);
>> +       if (!IS_ERR_OR_NULL(asus->wlan_led.dev))
>> +               led_classdev_unregister(&asus->wlan_led);
>>         if (asus->led_workqueue)
>>                 destroy_workqueue(asus->led_workqueue);
>>  }
>> @@ -465,6 +474,7 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
>>  static int asus_wmi_led_init(struct asus_wmi *asus)
>>  {
>>         int rv = 0;
>> +       u32 result;
>>
>>         asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
>>         if (!asus->led_workqueue)
>> @@ -498,6 +508,17 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
>>                         goto error;
>>         }
>>
>> +       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
>> +       if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
>> +               asus->wlan_led.name = "asus-wmi::wlan";
>> +               asus->wlan_led.brightness_set = wlan_led_set;
>
> Why no brightness_get ?
The return value from querying ASUS_WMI_DEVID_WIRELESS_LED  is not correct.
In my machine, I'll get 0x00050003 when querying its status no matter
the LED is on or off.
That's why I didn't provide a brightness_get() function.

> (note that if you decide to add wl_led_get() function that returns
> -ENODEV when not found (like for touchpad), please use directly
> instead of checking devstate above).
I'll wrap the devstate in a function, but won't provide a brightness_get()
Is that okay?

>
>> +               asus->wlan_led.flags = LED_CORE_SUSPENDRESUME;
>> +               asus->wlan_led.max_brightness = 1;
>> +               asus->wlan_led.default_trigger = "asus-wlan";
>> +               rv = led_classdev_register(&asus->platform_device->dev,
>> +                                          &asus->wlan_led);
>> +
>> +       }
>>  error:
>>         if (rv)
>>                 asus_wmi_led_exit(asus);
>> @@ -811,6 +832,9 @@ static int asus_new_rfkill(struct asus_wmi *asus,
>>         if (!*rfkill)
>>                 return -EINVAL;
>>
>> +       if (dev_id == ASUS_WMI_DEVID_WLAN)
>> +               rfkill_set_led_trigger_name(*rfkill, "asus-wlan");
>> +
>
> I think this is only needed because leds are created before rfkill
> switchs. You may also simply move rfkill_init() above led_init() (take
> care of fail_led, fail_rfkill too).
>
> Another solution is to call led_trigger_set_default() instead of
> rfkill_set_led_trigger_name()
I tried to exchange rfkill_init() and led_init() only in asus_wmi_add(),
and the LED didn't work anymore.
So, I think the current init sequence is correct and should not change it.

And while calling led_classdev_register() in asus_wmi_led_init()
it will call led_trigger_set_default() in the end of
led_classdev_register() function.

We still need to set the led trigger name to rfkill, so that our led function
will be called when rfkill status is changed.

>
>>         rfkill_init_sw_state(*rfkill, !result);
>>         result = rfkill_register(*rfkill);
>>         if (result) {
>> --
>> 1.7.9.5
>>
>
>
>
> --
> Corentin Chary
> http://xf.iksaif.net
> --
> To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Chia-Lin Kao(AceLan)
http://blog.acelan.idv.tw/
E-Mail: acelan.kaoATcanonical.com (s/AT/@/)

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

* Re: [PATCH 2/2] asus-wmi: update wlan LED through rfkill led trigger
  2012-07-26  8:12     ` AceLan Kao
@ 2012-07-26 12:11       ` Corentin Chary
       [not found]         ` <CAMz9Wg-H6dXXwF6Q7CsRaUFHg--4zVjhjuiEF93W5-BPeoP7kA@mail.gmail.com>
  0 siblings, 1 reply; 11+ messages in thread
From: Corentin Chary @ 2012-07-26 12:11 UTC (permalink / raw)
  To: AceLan Kao; +Cc: platform-driver-x86

On Thu, Jul 26, 2012 at 10:12 AM, AceLan Kao <acelan.kao@canonical.com> wrote:
> Dear Corentin,
>
> 2012/7/26 Corentin Chary <corentincj@iksaif.net>:
>> On Thu, Jul 26, 2012 at 5:34 AM, AceLan Kao <acelan.kao@canonical.com> wrote:
>>> For those machines with wapf=4, BIOS won't update the wireless LED,
>>> since wapf=4 means user application will take in chage of the wifi and bt.
>>> So, we have to update wlan LED status explicitly.
>>>
>>> But I found there is another wireless LED bug in launchpad and which is
>>> not in the wapf=4 quirk.
>>> So, it might be better to set wireless LED status explicitly for all
>>> machines.
>>>
>>> BugLink: https://launchpad.net/bugs/901105
>>>
>>> Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
>>> ---
>>>  drivers/platform/x86/asus-wmi.c |   24 ++++++++++++++++++++++++
>>>  1 file changed, 24 insertions(+)
>>>
>>> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
>>> index a13eb45..6ddfb0b 100644
>>> --- a/drivers/platform/x86/asus-wmi.c
>>> +++ b/drivers/platform/x86/asus-wmi.c
>>> @@ -183,6 +183,7 @@ struct asus_wmi {
>>>         struct device *hwmon_device;
>>>         struct platform_device *platform_device;
>>>
>>> +       struct led_classdev wlan_led;
>>>         struct led_classdev tpd_led;
>>>         int tpd_led_wk;
>>>         struct led_classdev kbd_led;
>>> @@ -452,12 +453,20 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
>>>         return value;
>>>  }
>>>
>>> +static void wlan_led_set(struct led_classdev *led_cdev,
>>> +                        enum led_brightness value)
>>> +{
>>> +       asus_wmi_set_devstate(ASUS_WMI_DEVID_WIRELESS_LED, value, NULL);
>>> +}
>>> +
>>>  static void asus_wmi_led_exit(struct asus_wmi *asus)
>>>  {
>>>         if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
>>>                 led_classdev_unregister(&asus->kbd_led);
>>>         if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
>>>                 led_classdev_unregister(&asus->tpd_led);
>>> +       if (!IS_ERR_OR_NULL(asus->wlan_led.dev))
>>> +               led_classdev_unregister(&asus->wlan_led);
>>>         if (asus->led_workqueue)
>>>                 destroy_workqueue(asus->led_workqueue);
>>>  }
>>> @@ -465,6 +474,7 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
>>>  static int asus_wmi_led_init(struct asus_wmi *asus)
>>>  {
>>>         int rv = 0;
>>> +       u32 result;
>>>
>>>         asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
>>>         if (!asus->led_workqueue)
>>> @@ -498,6 +508,17 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
>>>                         goto error;
>>>         }
>>>
>>> +       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
>>> +       if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
>>> +               asus->wlan_led.name = "asus-wmi::wlan";
>>> +               asus->wlan_led.brightness_set = wlan_led_set;
>>
>> Why no brightness_get ?
> The return value from querying ASUS_WMI_DEVID_WIRELESS_LED  is not correct.
> In my machine, I'll get 0x00050003 when querying its status no matter
> the LED is on or off.

Could I take a look to the DSDT ?

> That's why I didn't provide a brightness_get() function.
>
>> (note that if you decide to add wl_led_get() function that returns
>> -ENODEV when not found (like for touchpad), please use directly
>> instead of checking devstate above).
> I'll wrap the devstate in a function, but won't provide a brightness_get()
> Is that okay?
>
>>
>>> +               asus->wlan_led.flags = LED_CORE_SUSPENDRESUME;
>>> +               asus->wlan_led.max_brightness = 1;
>>> +               asus->wlan_led.default_trigger = "asus-wlan";
>>> +               rv = led_classdev_register(&asus->platform_device->dev,
>>> +                                          &asus->wlan_led);
>>> +
>>> +       }
>>>  error:
>>>         if (rv)
>>>                 asus_wmi_led_exit(asus);
>>> @@ -811,6 +832,9 @@ static int asus_new_rfkill(struct asus_wmi *asus,
>>>         if (!*rfkill)
>>>                 return -EINVAL;
>>>
>>> +       if (dev_id == ASUS_WMI_DEVID_WLAN)
>>> +               rfkill_set_led_trigger_name(*rfkill, "asus-wlan");
>>> +
>>
>> I think this is only needed because leds are created before rfkill
>> switchs. You may also simply move rfkill_init() above led_init() (take
>> care of fail_led, fail_rfkill too).
>>
>> Another solution is to call led_trigger_set_default() instead of
>> rfkill_set_led_trigger_name()
> I tried to exchange rfkill_init() and led_init() only in asus_wmi_add(),
> and the LED didn't work anymore.

Hum, how it didn't work ? the order should not change anything, very strange...

> So, I think the current init sequence is correct and should not change it.
>
> And while calling led_classdev_register() in asus_wmi_led_init()
> it will call led_trigger_set_default() in the end of
> led_classdev_register() function.

I know, but here you have to set the trigger by name because the led
is registered before the rfkill trigger. led_trigger_set_default()
will do exactly the same thing, but selecting the trigger specified in
.default_trigger instead of using a name (thus, avoiding the need to
revert the led trigger patch).

>
> We still need to set the led trigger name to rfkill, so that our led function
> will be called when rfkill status is changed.
>
>>
>>>         rfkill_init_sw_state(*rfkill, !result);
>>>         result = rfkill_register(*rfkill);
>>>         if (result) {
>>> --
>>> 1.7.9.5
>>>
>>
>>
>>
>> --
>> Corentin Chary
>> http://xf.iksaif.net
>> --
>> To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
>
> --
> Chia-Lin Kao(AceLan)
> http://blog.acelan.idv.tw/
> E-Mail: acelan.kaoATcanonical.com (s/AT/@/)
> --
> To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



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

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

* Re: [PATCH 2/2] asus-wmi: update wlan LED through rfkill led trigger
       [not found]         ` <CAMz9Wg-H6dXXwF6Q7CsRaUFHg--4zVjhjuiEF93W5-BPeoP7kA@mail.gmail.com>
@ 2012-07-27  8:07           ` Corentin Chary
  2012-07-27  8:55             ` AceLan Kao
  0 siblings, 1 reply; 11+ messages in thread
From: Corentin Chary @ 2012-07-27  8:07 UTC (permalink / raw)
  To: AceLan Kao; +Cc: platform-driver-x86

On Fri, Jul 27, 2012 at 4:20 AM, AceLan Kao <acelan.kao@canonical.com> wrote:
> Dear Corentin,
>
> 2012/7/26 Corentin Chary <corentincj@iksaif.net>:
>> On Thu, Jul 26, 2012 at 10:12 AM, AceLan Kao <acelan.kao@canonical.com> wrote:
>>> Dear Corentin,
>>>
>>> 2012/7/26 Corentin Chary <corentincj@iksaif.net>:
>>>> On Thu, Jul 26, 2012 at 5:34 AM, AceLan Kao <acelan.kao@canonical.com> wrote:
>>>>> For those machines with wapf=4, BIOS won't update the wireless LED,
>>>>> since wapf=4 means user application will take in chage of the wifi and bt.
>>>>> So, we have to update wlan LED status explicitly.
>>>>>
>>>>> But I found there is another wireless LED bug in launchpad and which is
>>>>> not in the wapf=4 quirk.
>>>>> So, it might be better to set wireless LED status explicitly for all
>>>>> machines.
>>>>>
>>>>> BugLink: https://launchpad.net/bugs/901105
>>>>>
>>>>> Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
>>>>> ---
>>>>>  drivers/platform/x86/asus-wmi.c |   24 ++++++++++++++++++++++++
>>>>>  1 file changed, 24 insertions(+)
>>>>>
>>>>> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
>>>>> index a13eb45..6ddfb0b 100644
>>>>> --- a/drivers/platform/x86/asus-wmi.c
>>>>> +++ b/drivers/platform/x86/asus-wmi.c
>>>>> @@ -183,6 +183,7 @@ struct asus_wmi {
>>>>>         struct device *hwmon_device;
>>>>>         struct platform_device *platform_device;
>>>>>
>>>>> +       struct led_classdev wlan_led;
>>>>>         struct led_classdev tpd_led;
>>>>>         int tpd_led_wk;
>>>>>         struct led_classdev kbd_led;
>>>>> @@ -452,12 +453,20 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
>>>>>         return value;
>>>>>  }
>>>>>
>>>>> +static void wlan_led_set(struct led_classdev *led_cdev,
>>>>> +                        enum led_brightness value)
>>>>> +{
>>>>> +       asus_wmi_set_devstate(ASUS_WMI_DEVID_WIRELESS_LED, value, NULL);
>>>>> +}
>>>>> +
>>>>>  static void asus_wmi_led_exit(struct asus_wmi *asus)
>>>>>  {
>>>>>         if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
>>>>>                 led_classdev_unregister(&asus->kbd_led);
>>>>>         if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
>>>>>                 led_classdev_unregister(&asus->tpd_led);
>>>>> +       if (!IS_ERR_OR_NULL(asus->wlan_led.dev))
>>>>> +               led_classdev_unregister(&asus->wlan_led);
>>>>>         if (asus->led_workqueue)
>>>>>                 destroy_workqueue(asus->led_workqueue);
>>>>>  }
>>>>> @@ -465,6 +474,7 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
>>>>>  static int asus_wmi_led_init(struct asus_wmi *asus)
>>>>>  {
>>>>>         int rv = 0;
>>>>> +       u32 result;
>>>>>
>>>>>         asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
>>>>>         if (!asus->led_workqueue)
>>>>> @@ -498,6 +508,17 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
>>>>>                         goto error;
>>>>>         }
>>>>>
>>>>> +       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
>>>>> +       if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
>>>>> +               asus->wlan_led.name = "asus-wmi::wlan";

Like you said, asus::wlan would be better.

>>>>> +               asus->wlan_led.brightness_set = wlan_led_set;
>>>>
>>>> Why no brightness_get ?
>>> The return value from querying ASUS_WMI_DEVID_WIRELESS_LED  is not correct.
>>> In my machine, I'll get 0x00050003 when querying its status no matter
>>> the LED is on or off.
>>
>> Could I take a look to the DSDT ?
> Sure, here comes the DSDT

It's 0x00050002 no ?
0x2 means "status unknown" (ASUS_WMI_DSTS_UNKNOWN_BIT).
So maybe you could check this bit, and set brightness_get only when
it's not set.

>>
>>> That's why I didn't provide a brightness_get() function.
>>>
>>>> (note that if you decide to add wl_led_get() function that returns
>>>> -ENODEV when not found (like for touchpad), please use directly
>>>> instead of checking devstate above).
>>> I'll wrap the devstate in a function, but won't provide a brightness_get()
>>> Is that okay?
>>>
>>>>
>>>>> +               asus->wlan_led.flags = LED_CORE_SUSPENDRESUME;
>>>>> +               asus->wlan_led.max_brightness = 1;
>>>>> +               asus->wlan_led.default_trigger = "asus-wlan";
>>>>> +               rv = led_classdev_register(&asus->platform_device->dev,
>>>>> +                                          &asus->wlan_led);
>>>>> +
>>>>> +       }
>>>>>  error:
>>>>>         if (rv)
>>>>>                 asus_wmi_led_exit(asus);
>>>>> @@ -811,6 +832,9 @@ static int asus_new_rfkill(struct asus_wmi *asus,
>>>>>         if (!*rfkill)
>>>>>                 return -EINVAL;
>>>>>
>>>>> +       if (dev_id == ASUS_WMI_DEVID_WLAN)
>>>>> +               rfkill_set_led_trigger_name(*rfkill, "asus-wlan");
>>>>> +
>>>>
>>>> I think this is only needed because leds are created before rfkill
>>>> switchs. You may also simply move rfkill_init() above led_init() (take
>>>> care of fail_led, fail_rfkill too).
>>>>
>>>> Another solution is to call led_trigger_set_default() instead of
>>>> rfkill_set_led_trigger_name()
>>> I tried to exchange rfkill_init() and led_init() only in asus_wmi_add(),
>>> and the LED didn't work anymore.
>>
>> Hum, how it didn't work ? the order should not change anything, very strange...
> I re-test again, the LED still works when only exchange rfkill_init()
> and led_init().
> Sorry for not test it carefully yesterday.

Ok, good.

> But when I remove rfkill_set_led_trigger_name() function, the LED stops working.
> The function key won't trigger the LED to change its status.
> But we still can turn it on/off through
> /sys/class/leds/asus-wmi::wlan/brightness
>
> (BTW, I should correct its name to asus::wlan, just like
> asus::touchpad and asus::kbd_backlight)
>
>>
>>> So, I think the current init sequence is correct and should not change it.
>>>
>>> And while calling led_classdev_register() in asus_wmi_led_init()
>>> it will call led_trigger_set_default() in the end of
>>> led_classdev_register() function.
>>
>> I know, but here you have to set the trigger by name because the led
>> is registered before the rfkill trigger. led_trigger_set_default()
>> will do exactly the same thing, but selecting the trigger specified in
>> .default_trigger instead of using a name (thus, avoiding the need to
>> revert the led trigger patch).
> I dig into the code, in net/rfkill/core.c +153
> static int rfkill_led_trigger_register(struct rfkill *rfkill)
> {
>         rfkill->led_trigger.name = rfkill->ledtrigname
>                                         ? : dev_name(&rfkill->dev);
>         rfkill->led_trigger.activate = rfkill_led_trigger_activate;
>         return led_trigger_register(&rfkill->led_trigger);
> }
> This is the only place that set the led_trigger.name,
> it will assign the name from dev_name(&rfkill->dev) if we didn't
> assign the name to rfkill->ledtrigname.
>
> And in include/linux/device.h +695
> static inline const char *dev_name(const struct device *dev)
> {
>         /* Use the init name until the kobject becomes available */
>         if (dev->init_name)
>                 return dev->init_name;
>
>         return kobject_name(&dev->kobj);
> }
>
> dev_name() will return the name dev->init_name or kobject_name(&dev->kobj)
> And while we register the rfkill by calling rfkill_alloc(), we will
> pass the name into the function.
> In net/rfkill/core.c +831
> The name only assign to "rfkill->name = name",
> so neither dev->init_name nor kobject_name(&dev->kobj) be assigned the
> rfkill name.
> That means there is no led trigger name be assigned while calling
> rfkill_led_trigger_register()
> So, I don't know how it works if we don't set the led trigger name by
> rfkill_set_led_trigger_name()

Oh, right, sorry for that, I didn't read that carrefully enought ! Yes
we need that ! (or a way to make all rfkill have a trigger correctly
named without calling that !).
Ok then :)

>
>>
>>>
>>> We still need to set the led trigger name to rfkill, so that our led function
>>> will be called when rfkill status is changed.
>>>
>>>>
>>>>>         rfkill_init_sw_state(*rfkill, !result);
>>>>>         result = rfkill_register(*rfkill);
>>>>>         if (result) {
>>>>> --
>>>>> 1.7.9.5
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Corentin Chary
>>>> http://xf.iksaif.net
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>>>
>>>
>>> --
>>> Chia-Lin Kao(AceLan)
>>> http://blog.acelan.idv.tw/
>>> E-Mail: acelan.kaoATcanonical.com (s/AT/@/)
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>
>>
>> --
>> Corentin Chary
>> http://xf.iksaif.net
>> --
>> To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
>
> --
> Chia-Lin Kao(AceLan)
> http://blog.acelan.idv.tw/
> E-Mail: acelan.kaoATcanonical.com (s/AT/@/)



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

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

* Re: [PATCH 2/2] asus-wmi: update wlan LED through rfkill led trigger
  2012-07-27  8:07           ` Corentin Chary
@ 2012-07-27  8:55             ` AceLan Kao
  0 siblings, 0 replies; 11+ messages in thread
From: AceLan Kao @ 2012-07-27  8:55 UTC (permalink / raw)
  To: Corentin Chary; +Cc: platform-driver-x86

Ok, now it works perfectly :)

2012/7/27 Corentin Chary <corentincj@iksaif.net>:
> On Fri, Jul 27, 2012 at 4:20 AM, AceLan Kao <acelan.kao@canonical.com> wrote:
>> Dear Corentin,
>>
>> 2012/7/26 Corentin Chary <corentincj@iksaif.net>:
>>> On Thu, Jul 26, 2012 at 10:12 AM, AceLan Kao <acelan.kao@canonical.com> wrote:
>>>> Dear Corentin,
>>>>
>>>> 2012/7/26 Corentin Chary <corentincj@iksaif.net>:
>>>>> On Thu, Jul 26, 2012 at 5:34 AM, AceLan Kao <acelan.kao@canonical.com> wrote:
>>>>>> For those machines with wapf=4, BIOS won't update the wireless LED,
>>>>>> since wapf=4 means user application will take in chage of the wifi and bt.
>>>>>> So, we have to update wlan LED status explicitly.
>>>>>>
>>>>>> But I found there is another wireless LED bug in launchpad and which is
>>>>>> not in the wapf=4 quirk.
>>>>>> So, it might be better to set wireless LED status explicitly for all
>>>>>> machines.
>>>>>>
>>>>>> BugLink: https://launchpad.net/bugs/901105
>>>>>>
>>>>>> Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
>>>>>> ---
>>>>>>  drivers/platform/x86/asus-wmi.c |   24 ++++++++++++++++++++++++
>>>>>>  1 file changed, 24 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
>>>>>> index a13eb45..6ddfb0b 100644
>>>>>> --- a/drivers/platform/x86/asus-wmi.c
>>>>>> +++ b/drivers/platform/x86/asus-wmi.c
>>>>>> @@ -183,6 +183,7 @@ struct asus_wmi {
>>>>>>         struct device *hwmon_device;
>>>>>>         struct platform_device *platform_device;
>>>>>>
>>>>>> +       struct led_classdev wlan_led;
>>>>>>         struct led_classdev tpd_led;
>>>>>>         int tpd_led_wk;
>>>>>>         struct led_classdev kbd_led;
>>>>>> @@ -452,12 +453,20 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
>>>>>>         return value;
>>>>>>  }
>>>>>>
>>>>>> +static void wlan_led_set(struct led_classdev *led_cdev,
>>>>>> +                        enum led_brightness value)
>>>>>> +{
>>>>>> +       asus_wmi_set_devstate(ASUS_WMI_DEVID_WIRELESS_LED, value, NULL);
>>>>>> +}
>>>>>> +
>>>>>>  static void asus_wmi_led_exit(struct asus_wmi *asus)
>>>>>>  {
>>>>>>         if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
>>>>>>                 led_classdev_unregister(&asus->kbd_led);
>>>>>>         if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
>>>>>>                 led_classdev_unregister(&asus->tpd_led);
>>>>>> +       if (!IS_ERR_OR_NULL(asus->wlan_led.dev))
>>>>>> +               led_classdev_unregister(&asus->wlan_led);
>>>>>>         if (asus->led_workqueue)
>>>>>>                 destroy_workqueue(asus->led_workqueue);
>>>>>>  }
>>>>>> @@ -465,6 +474,7 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
>>>>>>  static int asus_wmi_led_init(struct asus_wmi *asus)
>>>>>>  {
>>>>>>         int rv = 0;
>>>>>> +       u32 result;
>>>>>>
>>>>>>         asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
>>>>>>         if (!asus->led_workqueue)
>>>>>> @@ -498,6 +508,17 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
>>>>>>                         goto error;
>>>>>>         }
>>>>>>
>>>>>> +       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
>>>>>> +       if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
>>>>>> +               asus->wlan_led.name = "asus-wmi::wlan";
>
> Like you said, asus::wlan would be better.
>
>>>>>> +               asus->wlan_led.brightness_set = wlan_led_set;
>>>>>
>>>>> Why no brightness_get ?
>>>> The return value from querying ASUS_WMI_DEVID_WIRELESS_LED  is not correct.
>>>> In my machine, I'll get 0x00050003 when querying its status no matter
>>>> the LED is on or off.
>>>
>>> Could I take a look to the DSDT ?
>> Sure, here comes the DSDT
>
> It's 0x00050002 no ?
> 0x2 means "status unknown" (ASUS_WMI_DSTS_UNKNOWN_BIT).
> So maybe you could check this bit, and set brightness_get only when
> it's not set.
>
>>>
>>>> That's why I didn't provide a brightness_get() function.
>>>>
>>>>> (note that if you decide to add wl_led_get() function that returns
>>>>> -ENODEV when not found (like for touchpad), please use directly
>>>>> instead of checking devstate above).
>>>> I'll wrap the devstate in a function, but won't provide a brightness_get()
>>>> Is that okay?
>>>>
>>>>>
>>>>>> +               asus->wlan_led.flags = LED_CORE_SUSPENDRESUME;
>>>>>> +               asus->wlan_led.max_brightness = 1;
>>>>>> +               asus->wlan_led.default_trigger = "asus-wlan";
>>>>>> +               rv = led_classdev_register(&asus->platform_device->dev,
>>>>>> +                                          &asus->wlan_led);
>>>>>> +
>>>>>> +       }
>>>>>>  error:
>>>>>>         if (rv)
>>>>>>                 asus_wmi_led_exit(asus);
>>>>>> @@ -811,6 +832,9 @@ static int asus_new_rfkill(struct asus_wmi *asus,
>>>>>>         if (!*rfkill)
>>>>>>                 return -EINVAL;
>>>>>>
>>>>>> +       if (dev_id == ASUS_WMI_DEVID_WLAN)
>>>>>> +               rfkill_set_led_trigger_name(*rfkill, "asus-wlan");
>>>>>> +
>>>>>
>>>>> I think this is only needed because leds are created before rfkill
>>>>> switchs. You may also simply move rfkill_init() above led_init() (take
>>>>> care of fail_led, fail_rfkill too).
>>>>>
>>>>> Another solution is to call led_trigger_set_default() instead of
>>>>> rfkill_set_led_trigger_name()
>>>> I tried to exchange rfkill_init() and led_init() only in asus_wmi_add(),
>>>> and the LED didn't work anymore.
>>>
>>> Hum, how it didn't work ? the order should not change anything, very strange...
>> I re-test again, the LED still works when only exchange rfkill_init()
>> and led_init().
>> Sorry for not test it carefully yesterday.
>
> Ok, good.
>
>> But when I remove rfkill_set_led_trigger_name() function, the LED stops working.
>> The function key won't trigger the LED to change its status.
>> But we still can turn it on/off through
>> /sys/class/leds/asus-wmi::wlan/brightness
>>
>> (BTW, I should correct its name to asus::wlan, just like
>> asus::touchpad and asus::kbd_backlight)
>>
>>>
>>>> So, I think the current init sequence is correct and should not change it.
>>>>
>>>> And while calling led_classdev_register() in asus_wmi_led_init()
>>>> it will call led_trigger_set_default() in the end of
>>>> led_classdev_register() function.
>>>
>>> I know, but here you have to set the trigger by name because the led
>>> is registered before the rfkill trigger. led_trigger_set_default()
>>> will do exactly the same thing, but selecting the trigger specified in
>>> .default_trigger instead of using a name (thus, avoiding the need to
>>> revert the led trigger patch).
>> I dig into the code, in net/rfkill/core.c +153
>> static int rfkill_led_trigger_register(struct rfkill *rfkill)
>> {
>>         rfkill->led_trigger.name = rfkill->ledtrigname
>>                                         ? : dev_name(&rfkill->dev);
>>         rfkill->led_trigger.activate = rfkill_led_trigger_activate;
>>         return led_trigger_register(&rfkill->led_trigger);
>> }
>> This is the only place that set the led_trigger.name,
>> it will assign the name from dev_name(&rfkill->dev) if we didn't
>> assign the name to rfkill->ledtrigname.
>>
>> And in include/linux/device.h +695
>> static inline const char *dev_name(const struct device *dev)
>> {
>>         /* Use the init name until the kobject becomes available */
>>         if (dev->init_name)
>>                 return dev->init_name;
>>
>>         return kobject_name(&dev->kobj);
>> }
>>
>> dev_name() will return the name dev->init_name or kobject_name(&dev->kobj)
>> And while we register the rfkill by calling rfkill_alloc(), we will
>> pass the name into the function.
>> In net/rfkill/core.c +831
>> The name only assign to "rfkill->name = name",
>> so neither dev->init_name nor kobject_name(&dev->kobj) be assigned the
>> rfkill name.
>> That means there is no led trigger name be assigned while calling
>> rfkill_led_trigger_register()
>> So, I don't know how it works if we don't set the led trigger name by
>> rfkill_set_led_trigger_name()
>
> Oh, right, sorry for that, I didn't read that carrefully enought ! Yes
> we need that ! (or a way to make all rfkill have a trigger correctly
> named without calling that !).
> Ok then :)
>
>>
>>>
>>>>
>>>> We still need to set the led trigger name to rfkill, so that our led function
>>>> will be called when rfkill status is changed.
>>>>
>>>>>
>>>>>>         rfkill_init_sw_state(*rfkill, !result);
>>>>>>         result = rfkill_register(*rfkill);
>>>>>>         if (result) {
>>>>>> --
>>>>>> 1.7.9.5
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Corentin Chary
>>>>> http://xf.iksaif.net
>>>>> --
>>>>> To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in
>>>>> the body of a message to majordomo@vger.kernel.org
>>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>>
>>>>
>>>>
>>>> --
>>>> Chia-Lin Kao(AceLan)
>>>> http://blog.acelan.idv.tw/
>>>> E-Mail: acelan.kaoATcanonical.com (s/AT/@/)
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>>>
>>>
>>> --
>>> Corentin Chary
>>> http://xf.iksaif.net
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>
>>
>> --
>> Chia-Lin Kao(AceLan)
>> http://blog.acelan.idv.tw/
>> E-Mail: acelan.kaoATcanonical.com (s/AT/@/)
>
>
>
> --
> Corentin Chary
> http://xf.iksaif.net
> --
> To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Chia-Lin Kao(AceLan)
http://blog.acelan.idv.tw/
E-Mail: acelan.kaoATcanonical.com (s/AT/@/)

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

* Re: [PATCH 1/2] asus-wmi: record wlan status while controlled by userapp
  2012-07-26  9:13 AceLan Kao
@ 2012-07-28  9:51 ` Corentin Chary
  0 siblings, 0 replies; 11+ messages in thread
From: Corentin Chary @ 2012-07-28  9:51 UTC (permalink / raw)
  To: AceLan Kao; +Cc: platform-driver-x86

On Thu, Jul 26, 2012 at 11:13 AM, AceLan Kao <acelan.kao@canonical.com> wrote:
> If the user bit is set, that mean BIOS can't set and record the wlan
> status, it will report the value read from id ASUS_WMI_DEVID_WLAN_LED
> (0x00010012) while we query the wlan status by id ASUS_WMI_DEVID_WLAN
> (0x00010011) through WMI.
> So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED
> (0x00010012) while setting the wlan status through WMI.
> This is also the behavior that windows app will do.
>
> Quote from ASUS application engineer
> ===
> When you call WMIMethod(DSTS, 0x00010011) to get WLAN status, it may return
>
> (1) 0x00050001 (On)
> (2) 0x00050000 (Off)
> (3) 0x00030001 (On)
> (4) 0x00030000 (Off)
> (5) 0x00000002 (Unknown)
>
> (1), (2) means that the model has hardware GPIO for WLAN, you can call
> WMIMethod(DEVS, 0x00010011, 1 or 0) to turn WLAN on/off.
> (3), (4) means that the model doesn’t have hardware GPIO, you need to use
> API or driver library to turn WLAN on/off, and call
> WMIMethod(DEVS, 0x00010012, 1 or 0) to set WLAN LED status.
> After you set WLAN LED status, you can see the WLAN status is changed with
> WMIMethod(DSTS, 0x00010011). Because the status is recorded lastly
> (ex: Windows), you can use it for synchronization.
> (5) means that the model doesn’t have WLAN device.
>
> WLAN is the ONLY special case with upper rule.
>
> For other device, like Bluetooth, you just need use
> WMIMethod(DSTS, 0x00010013) to get, and WMIMethod(DEVS, 0x00010013, 1 or 0)
> to set.
> ===
>
> Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
> ---
>  drivers/platform/x86/asus-wmi.c |   21 ++++++++++++++++++++-
>  drivers/platform/x86/asus-wmi.h |    1 +
>  2 files changed, 21 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> index 77aadde..83d4cf7 100644
> --- a/drivers/platform/x86/asus-wmi.c
> +++ b/drivers/platform/x86/asus-wmi.c
> @@ -98,6 +98,7 @@ MODULE_LICENSE("GPL");
>  #define ASUS_WMI_DEVID_WIRELESS_LED    0x00010002
>  #define ASUS_WMI_DEVID_CWAP            0x00010003
>  #define ASUS_WMI_DEVID_WLAN            0x00010011
> +#define ASUS_WMI_DEVID_WLAN_LED                0x00010012
>  #define ASUS_WMI_DEVID_BLUETOOTH       0x00010013
>  #define ASUS_WMI_DEVID_GPS             0x00010015
>  #define ASUS_WMI_DEVID_WIMAX           0x00010017
> @@ -725,8 +726,21 @@ static int asus_rfkill_set(void *data, bool blocked)
>  {
>         struct asus_rfkill *priv = data;
>         u32 ctrl_param = !blocked;
> +       u32 dev_id = priv->dev_id;
>
> -       return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL);
> +       /*
> +        * If the user bit is set, BIOS can't set and record the wlan status,
> +        * it will report the value read from id ASUS_WMI_DEVID_WLAN_LED
> +        * while we query the wlan status through WMI(ASUS_WMI_DEVID_WLAN).
> +        * So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED
> +        * while setting the wlan status through WMI.
> +        * This is also the behavior that windows app will do.
> +        */
> +       if ((dev_id == ASUS_WMI_DEVID_WLAN) &&
> +            priv->asus->driver->wlan_ctrl_by_user)
> +               dev_id = ASUS_WMI_DEVID_WLAN_LED;
> +
> +       return asus_wmi_set_devstate(dev_id, ctrl_param, NULL);
>  }
>
>  static void asus_rfkill_query(struct rfkill *rfkill, void *data)
> @@ -1648,6 +1662,7 @@ static int asus_wmi_add(struct platform_device *pdev)
>         struct asus_wmi *asus;
>         acpi_status status;
>         int err;
> +       u32 result;
>
>         asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL);
>         if (!asus)
> @@ -1700,6 +1715,10 @@ static int asus_wmi_add(struct platform_device *pdev)
>         if (err)
>                 goto fail_debugfs;
>
> +       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result);
> +       if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT))
> +               asus->driver->wlan_ctrl_by_user = 1;
> +
>         return 0;
>
>  fail_debugfs:
> diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h
> index d43b667..cbe7ee2 100644
> --- a/drivers/platform/x86/asus-wmi.h
> +++ b/drivers/platform/x86/asus-wmi.h
> @@ -45,6 +45,7 @@ struct quirk_entry {
>  struct asus_wmi_driver {
>         int                     brightness;
>         int                     panel_power;
> +       int                     wlan_ctrl_by_user;
>
>         const char              *name;
>         struct module           *owner;
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Acked-by: Corentin Chary <corentin.chary@gmail.com>

Matthew could you merge this one ?
Thanks,


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

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

* [PATCH 1/2] asus-wmi: record wlan status while controlled by userapp
@ 2012-07-26  9:13 AceLan Kao
  2012-07-28  9:51 ` Corentin Chary
  0 siblings, 1 reply; 11+ messages in thread
From: AceLan Kao @ 2012-07-26  9:13 UTC (permalink / raw)
  To: platform-driver-x86, Corentin Chary

If the user bit is set, that mean BIOS can't set and record the wlan
status, it will report the value read from id ASUS_WMI_DEVID_WLAN_LED
(0x00010012) while we query the wlan status by id ASUS_WMI_DEVID_WLAN
(0x00010011) through WMI.
So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED
(0x00010012) while setting the wlan status through WMI.
This is also the behavior that windows app will do.

Quote from ASUS application engineer
===
When you call WMIMethod(DSTS, 0x00010011) to get WLAN status, it may return

(1) 0x00050001 (On)
(2) 0x00050000 (Off)
(3) 0x00030001 (On)
(4) 0x00030000 (Off)
(5) 0x00000002 (Unknown)

(1), (2) means that the model has hardware GPIO for WLAN, you can call
WMIMethod(DEVS, 0x00010011, 1 or 0) to turn WLAN on/off.
(3), (4) means that the model doesn’t have hardware GPIO, you need to use
API or driver library to turn WLAN on/off, and call
WMIMethod(DEVS, 0x00010012, 1 or 0) to set WLAN LED status.
After you set WLAN LED status, you can see the WLAN status is changed with
WMIMethod(DSTS, 0x00010011). Because the status is recorded lastly
(ex: Windows), you can use it for synchronization.
(5) means that the model doesn’t have WLAN device.

WLAN is the ONLY special case with upper rule.

For other device, like Bluetooth, you just need use
WMIMethod(DSTS, 0x00010013) to get, and WMIMethod(DEVS, 0x00010013, 1 or 0)
to set.
===

Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
---
 drivers/platform/x86/asus-wmi.c |   21 ++++++++++++++++++++-
 drivers/platform/x86/asus-wmi.h |    1 +
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 77aadde..83d4cf7 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -98,6 +98,7 @@ MODULE_LICENSE("GPL");
 #define ASUS_WMI_DEVID_WIRELESS_LED	0x00010002
 #define ASUS_WMI_DEVID_CWAP		0x00010003
 #define ASUS_WMI_DEVID_WLAN		0x00010011
+#define ASUS_WMI_DEVID_WLAN_LED		0x00010012
 #define ASUS_WMI_DEVID_BLUETOOTH	0x00010013
 #define ASUS_WMI_DEVID_GPS		0x00010015
 #define ASUS_WMI_DEVID_WIMAX		0x00010017
@@ -725,8 +726,21 @@ static int asus_rfkill_set(void *data, bool blocked)
 {
 	struct asus_rfkill *priv = data;
 	u32 ctrl_param = !blocked;
+	u32 dev_id = priv->dev_id;
 
-	return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL);
+	/*
+	 * If the user bit is set, BIOS can't set and record the wlan status,
+	 * it will report the value read from id ASUS_WMI_DEVID_WLAN_LED
+	 * while we query the wlan status through WMI(ASUS_WMI_DEVID_WLAN).
+	 * So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED
+	 * while setting the wlan status through WMI.
+	 * This is also the behavior that windows app will do.
+	 */
+	if ((dev_id == ASUS_WMI_DEVID_WLAN) &&
+	     priv->asus->driver->wlan_ctrl_by_user)
+		dev_id = ASUS_WMI_DEVID_WLAN_LED;
+
+	return asus_wmi_set_devstate(dev_id, ctrl_param, NULL);
 }
 
 static void asus_rfkill_query(struct rfkill *rfkill, void *data)
@@ -1648,6 +1662,7 @@ static int asus_wmi_add(struct platform_device *pdev)
 	struct asus_wmi *asus;
 	acpi_status status;
 	int err;
+	u32 result;
 
 	asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL);
 	if (!asus)
@@ -1700,6 +1715,10 @@ static int asus_wmi_add(struct platform_device *pdev)
 	if (err)
 		goto fail_debugfs;
 
+	asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result);
+	if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT))
+		asus->driver->wlan_ctrl_by_user = 1;
+
 	return 0;
 
 fail_debugfs:
diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h
index d43b667..cbe7ee2 100644
--- a/drivers/platform/x86/asus-wmi.h
+++ b/drivers/platform/x86/asus-wmi.h
@@ -45,6 +45,7 @@ struct quirk_entry {
 struct asus_wmi_driver {
 	int			brightness;
 	int			panel_power;
+	int			wlan_ctrl_by_user;
 
 	const char		*name;
 	struct module		*owner;
-- 
1.7.9.5

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

end of thread, other threads:[~2012-07-28  9:51 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-26  3:33 [PATCH 1/2] asus-wmi: record wlan status while controlled by userapp AceLan Kao
2012-07-26  3:34 ` [PATCH 2/2] asus-wmi: update wlan LED through rfkill led trigger AceLan Kao
2012-07-26  3:39   ` AceLan Kao
2012-07-26  5:19   ` Corentin Chary
2012-07-26  8:12     ` AceLan Kao
2012-07-26 12:11       ` Corentin Chary
     [not found]         ` <CAMz9Wg-H6dXXwF6Q7CsRaUFHg--4zVjhjuiEF93W5-BPeoP7kA@mail.gmail.com>
2012-07-27  8:07           ` Corentin Chary
2012-07-27  8:55             ` AceLan Kao
2012-07-26  5:22 ` [PATCH 1/2] asus-wmi: record wlan status while controlled by userapp Corentin Chary
2012-07-26  9:13 AceLan Kao
2012-07-28  9:51 ` Corentin Chary

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.