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 while we query the wlan status by id ASUS_WMI_DEVID_WLAN through WMI. 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. 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@xxxxxxxxxxxxx> --- drivers/platform/x86/asus-wmi.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 556cbb4..638facf 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 @@ -723,10 +724,34 @@ error_workqueue: */ static int asus_rfkill_set(void *data, bool blocked) { + static u32 wlan_status = 0xffffffff; struct asus_rfkill *priv = data; u32 ctrl_param = !blocked; + u32 dev_id = priv->dev_id; + int result; - 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. + * 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) { + if (wlan_status == 0xffffffff) + asus_wmi_get_devstate(priv->asus, + ASUS_WMI_DEVID_WLAN, + &wlan_status); + + if (wlan_status & + (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) + dev_id = ASUS_WMI_DEVID_WLAN_LED; + } + + result = asus_wmi_set_devstate(dev_id, ctrl_param, NULL); + + return result; } static void asus_rfkill_query(struct rfkill *rfkill, void *data) -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html