Tuesday, March 01, 2005

Determining 802.11 Signal Strength for Pocket PC

A very common request from Pocket PC developers is the ability to query the signal strength of an 802.11 wireless network signal being received by a WiFi enabled Pocket PC device. Here is some code that accomplishes this task for you.

This code basically queries the RSSI (Received Signal Strength Indicator) via the NDIS protocol. In your application, you call the GetFirstRFEthernetSignalStrength function to kick this all off as follows:

int nStrength = 0;
int nQuality = 0;
GetFirstRFEthernetSignalStrength(&nStrength, &nQuality);

The nStrength valule returned can then be used by your application to update a signal strength indcator such as a track bar or other UI element.




#include <ntddndis.h>
#include <nuiouser.h>
#include <winioctl.h>
#include <iphlpapi.h>

HRESULT GetSignalStrength(
TCHAR *ptcDeviceName,
int* piSignalStrength,
int* piSignalQuality
)
{
PNDISUIO_QUERY_OID queryOID;
DWORD dwBytesReturned = 0;
UCHAR QueryBuffer[sizeof(NDISUIO_QUERY_OID)
+sizeof(DWORD)];
HANDLE ndisAccess = INVALID_HANDLE_VALUE;
BOOL retval;
HRESULT hr;

// Attach to NDISUIO.
ndisAccess = CreateFile( NDISUIO_DEVICE_NAME,
0, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
INVALID_HANDLE_VALUE );
if ( ndisAccess == INVALID_HANDLE_VALUE )
return E_FAIL; // ????

// Get Signal strength
queryOID = (PNDISUIO_QUERY_OID)&QueryBuffer[0];
queryOID->ptcDeviceName = ptcDeviceName;
queryOID->Oid = OID_802_11_RSSI;

retval = DeviceIoControl( ndisAccess,
IOCTL_NDISUIO_QUERY_OID_VALUE,
(LPVOID) queryOID,
sizeof(NDISUIO_QUERY_OID) + sizeof(DWORD),
(LPVOID) queryOID,
sizeof(NDISUIO_QUERY_OID) + sizeof(DWORD),
&dwBytesReturned,
NULL);
if( retval && piSignalStrength && piSignalQuality )
{
hr = S_OK;
*piSignalStrength = *(DWORD *)&queryOID->Data;

//Here's Microsoft's interpretation
//of the return value
if(*piSignalStrength < -90)
*piSignalQuality = 0; // No signal
else if(*piSignalStrength < -81)
*piSignalQuality = 1; // Very low
else if(*piSignalStrength < -71)
*piSignalQuality = 2; // Low
else if(*piSignalStrength < -67)
*piSignalQuality = 3; // Good
else if(*piSignalStrength < -57)
*piSignalQuality = 4; // Very good
else
*piSignalQuality = 5; // Excellent
}
else
{
hr = E_FAIL;
}

CloseHandle( ndisAccess );

return hr;

}

BOOL GetFirstRFEthernetSignalStrength(
int* pSignalStrength,
int* pSignalQuality
)
{
BOOL retval = FALSE;

// Get the size of the adapters list.
DWORD size = 0;

GetAdaptersInfo( NULL, &size );

// Allocate space for the list.
IP_ADAPTER_INFO *info =
(IP_ADAPTER_INFO*)new char[ size ];

DWORD err;
if ((err = GetAdaptersInfo(info, &size ))
== NO_ERROR )
{
IP_ADAPTER_INFO *cinfo = info;
while ( cinfo )
{
// Check the interface media type for
// Ethernet, which both
// standard Ethernet and RF Ethernet will return.
if ( cinfo->Type == MIB_IF_TYPE_ETHERNET )
{
TCHAR wName[ MAX_ADAPTER_NAME_LENGTH + 4 ];
MultiByteToWideChar( CP_ACP, 0,
cinfo->AdapterName, -1,
wName,
sizeof( wName ) / sizeof( wName[ 0 ] ) );

// Try to get the signal strength.
//If it works, we
// return the information.
//If not, we move on.
if ( GetSignalStrength( wName,
pSignalStrength, pSignalQuality ) == S_OK )
{
retval = TRUE;
break;
}
}

// Go to the next adapter in the list.
cinfo = cinfo->Next;
}
}

// Don't forget to delete the allocation.
delete [] info;

return retval;
}

0 Comments:

Post a Comment

<< Home