Condividi tramite


Wireless Programming on Windows Mobile: supported or not supported?

  • I can’t take WZC for granted… but, at least, can I programmatically turn WiFi on and off?
  • ossvcs.dll’s Wireless Device Power Management Functions
  • WiFi driver is a Power Manager-controllable NDIS Miniport Driver
  • Introducing: RIL Driver and IP Helper APIs on WM6

As I mentioned in one of my first posts, WiFi Programming is something that depends so much on the WLAN driver developed by the OEM, that an ISV can’t take for granted some interfaces and develop a WiFi-based application that is device-independent. But if a WLAN driver implements the WZC interfaces, then an ISV developer may technically use WZC APIs, even if this is not supported by Microsoft as it is something OEM-dependent. For example, if you want to do so with managed code, then you must read the MSDN article I had already mentioned Building a Wi-Fi Discovery Application with the .NET Compact Framework 2.0 that Chris Tacke wrote some years ago. Also, make sure not to forget that many settings can be done through the Wi-Fi Configuration Service Provider, *IF* the OEM’s WiFi stack properly integrates with the standard WiFi architecture (i.e. it’s WZC-compatible). Note: I’m saying so because I recently worked on a case where querying the Wi-Fi CSP didn’t return anything even if the driver was loaded and even if there was an open connection, and in this case the relevant OEM had to provide the developer with a specific solution.

The issue is the following… ok, ISVs are not supported by Microsoft on controlling the WiFi connection by using WZC APIs because Microsoft can’t know what the OEM did with its WLAN driver: but… can at least ISVs use whatever API to even simply do very basic stuff such as programmatically turn it off and on? Does this simple task really depend on how the OEM developed the driver?

Looking for a solution over the web, you’d find 2 possible approaches, which seem to be OEM-independent:

  1. Use some undocumented APIs exposed by a DLL that is inside every \Windows folder of a WM device (this would also allow to interact with the other wireless radios of the device)
  2. Use Power Manager APIs with the WiFi driver, which is a NDIS Miniport driver controllable by Power Manager (valid for WiFi only)

{SIDE NOTE. Interestingly… while looking for those, I came across the following post: “ The most useful iPhone app I can't release ”. I honestly don’t know the Apple iPhone SDK, therefore can’t express myself on it and didn’t know that it “specifically prohibits using private framework API” (assuming that’s true, based on all the comments of that post): it’s simply interesting to know that WiFi Programmers have similar “non-technical” problems with iPhone platform as well. And I’m sure that Android ones benefit from the “oversights” of the other platforms! That’s the beauty of the competition in a market… (side-by-side note: remember that on Windows Mobile you can programmatically control Bluetooth through the Bluetooth CSP ). }

Let’s go back to Windows Mobile and examine the 2 approaches above.

 

1. Use some undocumented APIs exposed by a DLL that is inside every \Windows folder of a WM device (this would also allow to interact with the other wireless radios of the device)

This is an incredibly powerful approach, because it gives you the power of controlling the power state of all the wireless “devices”: Bluetooth, WiFi and Radio (i.e. the RIL = “Radio Interface Layer”: it’s the driver responsible for radio data connection (GPRS\EDGE\UMTS\..)). And it’s quite well known in the Mobile Community, we all know that \Windows\ossvcs.dll exposes some APIs (GetWirelessDevices, ChangeRadioState, etc, namely the “Wireless Device Power Management Functions”) that allow to develop your own Comm Manager (or Wireless Manager). And using those functions from within a managed application is even easier than on native applications, where you have to dynamically load the library and get the address of the function exposed with a particular ordinal: with managed apps, you can simply use the EntryPoint element of the DllImportAttribute.

Now, let’s pose the usual question: IS THIS SUPPORTED BY MICROSOFT TECHNICAL SUPPORT? The answer is simple here… Is it documented in the SDK? No: ergo it’s not officially supported… Or not? Those APIs are there: if the Dev Team didn’t want ISVs to use them then it wouldn’t develop a DLL which exposes them. Since the solution is well known in the Community and proved to work correctly in most cases, my personal opinion is that the problem is with the documentation here, which is simply missing for those APIs. I’ve asked the Product Group to consider adding the documentation in the public WM SDK… let’s see what that’ll sort out.

Just to be clear, even if one day those Wireless Device Power Management APIs will be fully documented and ready to be used by ISVs, what more can Microsoft Technical Support do after verifying that an ISV used the functions correctly? If those Wireless Device Power Management Functions don’t work correctly with one of the wireless drivers, chances are that the problem is with the driver, not with the functions (considering that the same APIs work correctly in other cases). And who develops the driver and technically has the ability to give support about it? Only the OEM…

 

2. Use Power Manager APIs with NDIS Miniport driver (valid for WiFi only)

If you look at pm.h header file of the WM5\6 SDKs, you’ll find a constant, which is is even public for 5.0 here and for 6.x here:

 #define PMCLASS_NDIS_MINIPORT           TEXT("{98C5250D-C29A-4985-AE5F-AFE5367E5006}")

If you examine the registry contents at [HKLM\System\CurrentControlSet\Control\Power\State], you’ll see “devices” whose power-state can be controlled thru Power Manager APIs, accordingly to the SDK Documentation. One of those devices is the WiFi driver, described as “ {98C5250D-C29A-4985-AE5F-AFE5367E5006}\<device name chosen by the OEM> ” (The name can be seen also for example in the IPConfig section of the log generated by the Windows Mobile Network Analyzer PowerToy). Since the device appears under that registry key, an ISV can programmatically control its power state by using the documented Power Manager API SetDevicePower():

 [DllImport("coredll.dll", SetLastError = true)] 
private static extern int SetDevicePower(string pvDevice, int dwDeviceFlags, DevicePowerState DeviceState); 

private enum DevicePowerState : int 
{ 
    Unspecified = -1, 
    D0 = 0, // Full On: full power, full functionality 
    D1, // Low Power On: fully functional at low power/performance 
    D2, // Standby: partially powered with automatic wake 
    D3, // Sleep: partially powered with device initiated wake 
    D4, // Off: unpowered 
}

private const int POWER_NAME = 0x00000001;

So, to turn the WiFi ON:

 string driver = Utilities.WiFi.FindDriverKey(); 
SetDevicePower(driver, POWER_NAME, DevicePowerState.D0);

And OFF:

 string driver = Utilities.WiFi.FindDriverKey(); 
SetDevicePower(driver, POWER_NAME, DevicePowerState.D4);

Utilities.WiFi.FindDriverKey() is simply a function that returns the whole registry key name of the key containing the NDIS MINIPORT class GUID defined in the SDK’s pm.h:

 private static string FindDriverKey() 
{ 
     string ret = string.Empty; 

     //#define PMCLASS_NDIS_MINIPORT           TEXT("{98C5250D-C29A-4985-AE5F-AFE5367E5006}") 
     //(From "c:\Program Files (x86)\Windows Mobile 6 SDK\PocketPC\Include\Armv4i\pm.h") 
     string WiFiDriverClass= "{98C5250D-C29A-4985-AE5F-AFE5367E5006}";  

     foreach (string tmp in Registry.LocalMachine.OpenSubKey("System\\CurrentControlSet\\Control\\Power\\State", false).GetValueNames()) 
     { 
         if (tmp.Contains(WiFiDriverClass)) 
         { 
             ret = tmp; 
             break; 
         } 
     } 

     return ret; 
}

This proved to work on some devices I’ve tested it with, after reboots and also consistently with the Wireless Manager\Comm Manager of the device. I’ve found a forum post stating that on iPAQ devices this approach doesn’t work (and this is in line with the fact that HP provided a DLL within its private SDK exposing specific APIs to interact with their driver), however I tested this approach on an iPAQ Smartphone and it worked as well.

Now, the usual question: IS THIS SUPPORTED OR NOT BY MICROSOFT TECHNICAL SUPPORT? Every single detail an ISV uses in this approach is documented, hence supported. Cool! But… again, as before… what more can Microsoft Technical Support do after verifying that the ISV used the functions above correctly? If a Power Manager API doesn’t work correctly with a driver, chances are that the problem is with the driver, not with the PM API (considering that the same API works correctly in other cases). And who develops the driver and has technically the ability to give support about it? Again, the OEM…

 

I hope things are a bit clearer now… just let me know in case that’s not true!

 

Cheers,

~raffaele

 

P.S.: There’s an interesting point about NDIS Miniport drivers. On WM5, Microsoft's recommendation to OEMs was to implement the RIL Driver as PPP Adapter. Among other things, that allowed developers using IP Helper APIs to easily retrieve the related adapter information because the string "[Cellular Line]" was contained in the Adapter's name, for example thru the GetAdaptersInfo() API. Now, starting on WM6 Microsoft encourages OEMs to implement the RIL as NDIS Miniport driver, because this way the device will be ready to support simultaneous data calls (with PPP you can’t do that): "[...] One advantage of using WWAN-based GPRS connections is the ability to establish multiple GPRS connections simultaneously" (Establishing a WWAN-based GPRS Connection).

Note that not every single WM6.x device has already the RIL implemented as NDIS Miniport driver, demonstrating once again how OEMs have complete power on this. So, if you use IP Helper APIs or simply look the ipconfig report of the Windows Mobile Network Analyzer PowerToy, on WM6 devices where the OEM hasn’t yet “upgraded” the RIL you’ll still see

  • PPP Adapter [Cellular Line] :

    • Adapter Name ...... : Cellular Line

while on those WM6 devices where the RIL is already implemented as NDIS Miniport driver

  • Ethernet adapter Local Area Connection:

    • Adapter Name ...... : WWAN1-IBOX.TIM.IT-1 (for example)

therefore it's no longer distinguished from for example the WiFi connection:

  • Ethernet adapter Local Area Connection:

    • Adapter Name ...... : TNETW12511 (for example)

At TCP\IP Protocol level (e.g. by using IP Helper API GetAdaptersInfo), on those WM6 devices where the OEM followed Microsoft's recommendations for the RIL there’s no way to distinguish if a connection is WLAN (=WiFi) or WWAN (=RIL). In future I plan to post about another approach, probably based on NDISUIO (“NDIS User-mode I/O”)… I firstly need to be sure I’ll talk about something “SUPPORTED”… (that’s always my #1 priority! Or not? :-)

 

P.P.S.: Happy birthday to this blog!! THANK EVERYONE FOR READING\COMMENTING\CONTACTING ME, I couldn’t absolutely imagine the success it had in our Community (does it really deserve it? :-), so thanks again!! If you have any suggestion on anything, just let me know!

Comments

  • Anonymous
    March 16, 2009
    Hi Raffaele,                  To give a brief intro, I have a WM AKU 614 OS image built with RIL driver (ported for a customer platform). Till date the RIL driver has been working on the PPP based GPRS connections and now we have requirement to implement NDIS based GPRS connections. The image was built with the environment variable "IMGNDISGPRS" enabled. The registry entry governing the No. of contexts and type of GPRS connections ( whether PPP or NDIS) was also configured for NDIS gprs. When establishing a data connection, the PDP context is getting activated  & IP address is getting assigned but there is no data flow between the RIL proxy and the RIL driver. Now, The RIL driver doesn't expose the NDIS interface. From MSDN documentation I understand that a RIL miniport driver has to be  inserted betweeb the RIL proxy and the driver. This RIL miniport driver exposes NDIS interface. But the same document reveals that RIL Miniport deriver is supported on WINCE and not on Windows Mobile. Can you please let me know  what is the process involved in making the RIL driver as a NDIS adapter ( if my understanding is correct!). Is there any more configuration changes that has to be done to denote the Connection Manager about the availability of NDIS based GPRS in RIL. else how do I enable NDIS based GPRS in RIl driver. Your inputs on these queries will help me a lot thanks, Vasanth

  • Anonymous
    March 16, 2009
    Hi Vasanth, thanks for your question! Don't mix up the public doc for Windows CE's OEMs with the private doc for Windows Mobile's OEMs, which is not the one available on MSDN (are you doing that?). In other words, it may well be that RIL on Windows Mobile has something different than the one on Windows CE. My understanding is that you're building your own Windows Mobile-based image, so I would suggest asking for support to OEM Services Support, which you should be eligible for. My help on the Application Development-side might be very limited here... HTH, thanks and bye! ~raffaele

  • Anonymous
    March 16, 2009
    Hi raffaele,                 Well, I've been using the WINCE MSDN documentation as a reference. Now that I understand the possibility of differences in the RIL implementation between the CE and Mobile, I guess I will get in touch with the OEM Services Support. Thanks, Vasanth

  • Anonymous
    November 19, 2009
    Hi Raffaele, Ur article is really helpful! However do you think about using Windows Zero Config API?

  • Anonymous
    November 22, 2009
    Thanks for your comment! Yes, I thought about about WZC APIs... I mentioned them at the beginning of the post, stating that an ISV may technically be able to use them only if the OEM's WLAN Driver is WZC-compliant. So the point is that you can't take them for granted and at today there's no standard way. Thanks again, bye! ~raffaele

  • Anonymous
    December 16, 2009
    hi....i wish to know how i can connect my mobile using the NDISUIO, by code in c++ or c#, i have the instruction for turn on and turn off, but i need the code for connect and disconnect. thenk you

  • Anonymous
    December 29, 2009
    Thanks for your question. WinMo Application Developers are encouraged (and supported) on using Connection Manager APIs to deal with device connectivity when required. Basically, once you set up ConnMgr through CM APIs or XML Provisioning (CM_xx Configuration Service Providers), and set up WiFi through WZC APIs if the OEM's WLAN Driver implemented it or through CM_WiFiEntries, then it's done -- when the device will require connectivity and WiFi is on and available, it would connect automatically. On the other hand, it may also be that the OEM who developed the WLAN Driver also exposed custom private APIs to innerly connectdisconnect it. HTH! ~raffaele

  • Anonymous
    June 27, 2010
    Hi Raffaele Limosani, My hearty congratulate you for such a helpful blog........... It helped me a lot this article........... Once again Thank You very much.............

  • Anonymous
    June 29, 2010
    Hi Raffaele Limosani, My hearty congratulate you for such a helpful blog........... It helped me a lot this article........... Once again Thank You very much.............

  • Anonymous
    January 27, 2011
    how to disable/enable WIFI radio on windows-ce ? (not windows-mobile)

  • Anonymous
    August 18, 2014
    Until today your blog is being helpful. Thanks

  • Anonymous
    November 02, 2014
    I used this code, it enables wifi, but somehow in a few seconds wifi disables again.. any one can help?