Dear Corentin, >From ASUS, for old machines, they use 0x00010012 to turn on/off the wlan led but now use 0x00010002 So, 0x00010012 is reused to store the wlan status nowadays if wlan is controlled by user. Best regards, AceLan Kao. 2012/7/23 AceLan Kao <acelan.kao@xxxxxxxxxxxxx>: > Dear Corentin, > > 2012/7/23 Corentin Chary <corentincj@xxxxxxxxxx>: >> On Mon, Jul 23, 2012 at 5:27 AM, AceLan Kao <acelan.kao@xxxxxxxxxxxxx> wrote: >>> Dear Corentin, >>> >>> 2012/7/20 Corentin Chary <corentincj@xxxxxxxxxx>: >>>> On Fri, Jul 20, 2012 at 5:26 AM, AceLan Kao <acelan.kao@xxxxxxxxxxxxx> 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 >>>>> 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 >>>> >>>> Will it handle the LED too, or do you have to call 0x00010012 ? >>> In this case, we don't have to worry about the LED, BIOS will pull >>> up/down the LED pin >>> after receiving the enable/disable wireless command through WMI. >>> >>>> >>>>> (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. >>>> >>>> That means WMIMethod(DSTS, 0x00010011, 0) will do nothing ? Or will it >>>> control both the led and the device ? >>> Yes, WMIMethod(DSTS, 0x00010011, 0) will do nothing if we try to >>> enable/disable it. >>> It won't turn on/off the wifi nor the LED. >>> But, we still can read the status of wireless through this command, but >>> need to use 0x00010012 to set wifi status. >>> >>>> How can you then call WMIMethod(DSTS, 0x00010012, 0/1) since nobody >>>> switched wlan on or off ? >>>> If you just want a way to control the led, expose it under >>>> /sys/class/leds, and remove wlan from /sys/class/rfkill if it doesn't >>>> work. >>> ASUS' BIOS engineer told us that it's a way to change the status of >>> wifi(read from id 0x00010011) >>> by writing the value to 0x00010012, and ms windows application do that as well. >>> It's a poor design by ASUS' BIOS, they really surprise me while telling me that. >>> >>> But, the advantage of doing this is the value stored in the 0x00010012 >>> (should be read from id 0x00010011) will be preserved to next reboot. >>> So that we can track the status of wifi. >>> And once we can get the correct wifi state, we then can block/unblock >>> wifi while boot up. >>> And it will have the same behavior as the one controlled by BIOS. >> >> So, in this case, 0x00010012 controls: >> - The LED >> - The LED *and* the WLAN device >> - The WLAN device >> - Nothing, it just stores a value >> >> Just to be sure to understand ... Be sure to add a comment when using >> 0x00010012 to tell exactly what it does. > From what I have heard, it should be 4 (stores a value but should be > read from 0x00010011, instead of from 0x00010012) > But I also raise this question to our PM and he will help us to > clarify this from ASUS tomorrow. > >> >>>> >>>>> (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 >>>> >>>> What's the difference between this one and ASUS_WMI_DEVID_WIRELESS_LED ? >>>> What is really 0x00010002 ? >>> That's another weird part, that's the name defined in the ASUS WMI spec. >>> Please see the attached pic. >>> 0x00010002 is the read one which can control the wireless LED, >>> I don't know why there is another one exists in the spec. >>> >>>>> #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; >>>> >>>> Don't use a static variable, add a field into struct asus_wmi instead. >>> got it. >>> >>>> >>>>> 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); >>>> >>>> Maybe you could read that on startup instead of using lazy loading ? >>>> Read the state of the wlan device, and set a flag "led should be controlled" >>> ok >>> >>>> >>>>> + 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) >>>> >>>> While this patch work, I'll prefer an approach using a led class and a >>>> led trigger. The led trigger would be set by default, but the user >>>> would also be able to switch the trigger to another one, or to control >>>> the led using /sys/class/leds/ >>> I think the problem is not so seriously, we just need to record the wifi status >>> if the wifi device is controlled by application. >>> And the solution is to store the status in 0x00010012. >>> So that rfkill could work as expected. >>> >>> Best regards, >>> AceLan Kao. >>> >>> -- >>> 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@xxxxxxxxxxxxxxx >> 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/@/) -- 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@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html