Controlling the Radio Devices


Introduction


The number of mobile devices manufacturers is quite big at the moment, so for the developers there are many platforms out on the market and their software must function properly on each of them.
Most of the programming aspects are covered by the available APIs. General things like drawing a fancy interface or having a minimum of functionality will work without any issues on all the Windows Mobile platforms. But if we need to control the Hardware installed, its a totally different story. Each manufacturer works with his own providers of electronic components. Each electronic module has some particularities, some parameters that one should know if he is supposed to work with that equipment.
For this article we will focus on a way of controlling the Radio Devices. Currently, most Mobile Devices contain a Bluetooth module, a Phone module and a Wireless Lan module (WiFi). I could say we are lucky that a general solution was provided by Microsoft, but again, that solution lies buried in the ossvcs.dll file.


Getting into details

Usually we need to toggle on or off a particular Radio Device. We would need this for a Profiler software, for a Battery saver, or for many other reasons. Also we would need to know the status of a particular Radio Device.
What many don't know is that ossvcs.dll exports functions by ordinal numbers, NOT by names. For this article we will use the following exports:

#define GetWirelessDevice_ORDINAL 276
#define ChangeRadioState_ORDINAL 273
#define FreeDeviceList_ORDINAL 280

The ordinal numbers and the prototype of the exported functions are the biggest concern, because the ossvcs.dll is in the ROM and is usually a hard job to obtain this data.

Here are the prototypes of the functions that we need

//imports from ossvcs.dll
typedef LRESULT (CALLBACK* _GetWirelessDevices)(RDD **pDevices, DWORD dwFlags);
typedef LRESULT (CALLBACK* _ChangeRadioState)(RDD* pDev, DWORD dwState, SAVEACTION sa);
typedef LRESULT (CALLBACK* _FreeDeviceList)(RDD *pRoot);

So after we load the ossvcs.dll with LoadLibrary, and prepare the prototype of the functions we can start controlling the Radio Devices.

BOOL InitDLL()
{
g_DllWrlspwr = LoadLibrary(TEXT("ossvcs.dll"));
if (g_DllWrlspwr == NULL)
return FALSE;
pGetWirelessDevices = (_GetWirelessDevices)GetProcAddress(g_DllWrlspwr,MAKEINTRESOURCE(GetWirelessDevice_ORDINAL));
if (pGetWirelessDevices == NULL)
return FALSE;

pChangeRadioState = (_ChangeRadioState)GetProcAddress(g_DllWrlspwr,MAKEINTRESOURCE(ChangeRadioState_ORDINAL));
if (pChangeRadioState == NULL)
return FALSE;

pFreeDeviceList = (_FreeDeviceList)GetProcAddress(g_DllWrlspwr,MAKEINTRESOURCE(FreeDeviceList_ORDINAL));
if (pFreeDeviceList == NULL)
return FALSE;
return TRUE;
}

To get the current status a simple query would be:

DWORD dwWifi, dwPhone, dwBT;
GetWDevState(&dwWifi, &dwPhone, &dwBT);
// For dwBT == 1 or dwBT == 2 The Bluetooth Radio is ON
// For dwPhone == 1 The Phone Radio is ON
// For dwWifi == 1 The WiFi Radio is ON

GetWDevState works by calling the pGetWirelessDevices, parsing the output provided, item by item, and then deallocating the used memory with pFreeDeviceList, as you can see in the sample. A memory leak of 8KB results from this process, indicating that pFreeDeviceList is not functioning properly. I would be happy if any of the readers of this article figures out the cause of this.
For changing the state of a particular Radio Device use SetWDevState:

//0 for stop, 1 for start
SetWDevState( RADIODEVICES_BLUETOOTH, 0);
SetWDevState( RADIODEVICES_PHONE, 0);
SetWDevState( RADIODEVICES_MANAGED, 0);

SetWDevState uses pGetWirelessDevices, pChangeRadioState and pFreeDeviceList.

As usual, I have also prepared a sample, for a better understanding of what this article descriebes:

Radio Devices C++ Sample



Your feedback is most welcomed, please feel free to contact me by mail or on the Teksoft Forums: www.teksoftco.com/forum


Radu Motisan
www.teksoftco.com
October 22, 2006