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/@/) -- 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