Skip to main content

Developing a WebSphere Everyplace Connection Manager Status DLL

Stephen Pipes (pipessd@uk.ibm.com), IT Specialist, IBM
Author photo: Stephen Pipes
Stephen Pipes is an IT Specialist at IBM's Hursley Park Labs in the UK, where he is a member of the Pervasive Computing group, providing consultancy services for customers in Europe, the Middle East, and Africa. Stephen is an expert in WebSphere Application Server security and regularly presents at technical conferences on the subjects of pervasive computing, security, and Java.

Summary:  IBM® WebSphere® Everyplace® Connection Manager supports a wide variety of networking devices on a number of server and client operating systems, including Win32™, Linux™, AIX®, Solaris, Pocket PC, Mobile 2003, Palm and Symbian. To access such a large array of devices in a consistent fashion, Connection Manager makes use of common interfaces, typically provided by the operating system and implemented by device vendors. This means that Connection Manager can use functionality without having to provide drivers for every device. However, sometimes these interfaces don't accommodate a certain required function. Connection Manager has created a work-around for these limitations by providing a set of additional interfaces that you can implement. This article describes one such interface, the status DLL interface, and demonstrates how you can use it to enhance the functionality of the Connection Manager Mobility Client on Windows™ 32-bit operating systems.

Date:  08 Jun 2005
Level:  Intermediate
Activity:  253 views

Introduction

The status DLL documented in this article was developed to extend the functionality of the Mobility Client to report the signal strength of a UMTS modem, which is a PCMCIA device that provides wireless GPRS (often referred to as 2.5G) and UMTS (3G) wide area network data connections. A Win 32 Dial-Up Network (DUN) driver is provided with the modem. This driver registers with Windows™ and provides two links in the Network Connections panel on Windows XP, as shown below.


Figure 1. Windows XP Network Connections panel
Windows XP Network Connections panel

Double-clicking the second link, internet.3G-GPRS, initiates a data connection and enables UMTS, if available. The Mobility Client uses this mechanism to establish a connection with the Connection Manager. However, the driver does not provide a means of assessing the signal strength during a connection. This is important for roaming purposes, as the Received Signal Strength Indication (RSSI) is considered the most effective way of predicting connection quality. If the quality drops below a predefined threshold, the Mobility Client needs to roam to another network in order to stay in contact with the Connection Manager. The solution is to implement Connection Manager's status DLL interface.

Note: RSSI should not be confused with media sense, which is a feature supported by Windows to detect whether the network media is in a link state. This state refers to the physical media connecting or inserting itself on the network and is available through NDIS.

A working knowledge of C++ is assumed for this article.


The status DLL

The status DLL provides a set of capabilities that extend the Mobility Client. These capabilities include indicators for:

  • Signal strength
  • Battery mode
  • Transmitter control (enabled/disabled)
  • Sleep mode control (enter/exit)
  • Interface control (suspend/resume)

Many modem vendors supply toolkits that can be used to programmatically obtain relevant information from their devices. The status DLL retrieves the RSSI value from the modem and presents it to the Mobility Client, so that it is aware when the radio signal strength is too low to be useful.

The status DLL is part of the Mobility Client Toolkit, which can be downloaded for free from the IBM support Web site. The toolkit supports programming in C/C++, Visual Basic (via an ActiveX wrapper), and Java™. A sample DLL, written in C++, is supplied with the toolkit. Refer to the toolkit documentation for more information and installation instructions. You might find it useful to refer to the sample code while reading this article.

A complete status DLL is not provided with this article; only the salient parts that demonstrate the workings of a status DLL are included. In order to write a complete status DLL, you can extend the framework provided in this article with device-specific function calls.

The status DLL is multi-threaded due to the asynchronous nature of the interactions with devices. Activities tend to be asynchronous in that a message will be sent to the device, then the DLL will wait for a response, while another thread continues processing. This threading is demonstrated in the status DLL sample, so a detailed understanding of how multithreading works is not required.


System libraries and header files

The DLL provides a header file, artapi.h, that includes function, return and message definitions used by the status DLL. It also defines the ART_API_MESSAGE type as shown:

typedef struct {
	eMsg	msgId;			/* ART Message Identifier */
	long	hInterface;		/* Interface handle */
	eRC	rc;			/* Return code */
	long	value1;			/* Optional value */
	long	value2;			/* Optional value */
	long	chDataLen;		/* Data length (if any) */
	char	chData[1];		/* Message specific data */
} ART_API_MESSAGE;

Of the numerous return codes (of type eRC), eOK represents success. Refer to the header file for the complete list.

This header file is used to pass messages between the status DLL and the Mobility Cient. The actual messages (of type eMsg) are defined in artapi.h and include eMsg_SignalStrength and eMsg_NetworkCapabilities, which calls for the status DLL to declare its capabilities.


Inspecting the DLL

The usual DllMain function is declared as shown below. This provides a common initial entry point into the DLL.

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
    return TRUE;
}

Three additional functions are implemented in the status DLL:

  • Status_Init is called by the Mobility Client during initialization and allows configuration of the status DLL by calling its Initialize function.
  • The return code reports whether initialization was successful and if not, the DLL will be unloaded and not used. A pointer to the status callback function is passed as an argument (used here to report signal strength), as is a pointer to the Connection Manager logging function.
  • Finally, a handle, which must be included when calling the callback functions, is passed.

All three arguments are passed on to the UMTS instance, which contains lifecycle and notification functions for the modem class, as shown below:

MODEMSTATUS_API eRC Status_Init(void *handle, Status_Callback_Func_t pCallbackFunc, Status_Log_Func_t pLogFunc)
{
	eRC retval = eOK;
	
	if (!pUMTS)
	{
		pUMTS = new UMTS;
		retval = pUMTS->Initialize(handle, pCallbackFunc, pLogFunc);
	}
	
	return retval;
}

Status_Request is called by the Mobility Client to determine the status of a particular capability. The status DLL provides two capabilities, defined by ART_SIGNALSTRENGTH and ART_RANGE_EVENTS. In other words, the status DLL is capable of reporting the signal strength and will determine whether the modem is in or out of signal coverage. You can also implement other capabilities, such as ART_BATTERYSTRENGTH, ART_SIGNALQUALITY and ART_SHORTHOLD (whether the modem supports short hold). See the artapi.h header file for a complete list of possible capabilities. The Mobility Client may also request a list of all capabilities provided by the status DLL, as described later.

MODEMSTATUS_API eRC Status_Request(eMsg requestType)
{
	if (pUMTS)
		return pUMTS->HandleAPIRequest(requestType);
	else 
		return eErrFailed;
}

Status_Exit is called by the Mobility Client when the interface is closed, and unloads the DLL, if loaded. The code calls InterlockedIncrement, which ensures that the DLL is not terminating under another thread at that time.

MODEMSTATUS_API eRC Status_Exit()
{
	if (InterlockedIncrement(&terminating) == 1)
	{
		if (pUMTS)
		{
			pUMTS->Terminate();
		}
		
		delete pUMTS;
		pUMTS = NULL;
	}
    return eOK;
}

Each function is declared as MODEMSTATUS_API, which indicates to the compiler that it should be exported as a DLL symbol. These functions can be used as a template for all status DLLs and do not contain any modem specifics. Refer to the sample DLL in the Mobility Toolkit for complete code listings.

The C++ status DLL is dynamically linked with the artapi.dll library, which is installed in the Windows system directory (for Win32). For static linking purposes, a file called artapi.lib is provided with the toolkit.


Starting the status thread

The status DLL must monitor the modem on a regular basis to determine whether it is in or out of range and to report the signal strength. In order to do this, a new thread is created and associated with the statusThread function. The thread is spawned in the Initialize function defined in the modem-specific UMTS class, as shown:

eRC UMTS::Initialize(void *correlator_handle, Status_Callback_Func_t* pCallbackFunc, Status_Log_Func_t* pLogFunc)
{
	// initialise variables here

	// log function entry
pLogFunc(m_correlator, _T("UMTS::Initialize entry"));

	// initialise modem here

	// start capturing events
	m_threadID = CreateThread(NULL, 0, staticStatusThread, this, 0, NULL);
	if (m_threadID == NULL)
	{
		long error = GetLastError();
	}

	// log function exit
	m_log(m_correlator, _T("UMTS::Initialize exit"));
	return eOK;
}

You can send trace events to the Mobility Client at any point in the status DLL by calling the status log function. This provides an easy-to-use mechanism for debugging purposes. These messages appear in the trace files and in the trace viewer, if the correct level of tracing is enabled. The correlator handle must also be passed back as an argument.

The thread is created by calling the CreateThread function, provided by the Microsoft™ Active Template Library. A pointer to the function that the thread should execute is passed as an argument. This is a static method called staticStatusThread, which calls a non-static member function called statusThread. The actual work of extracting the signal strength is performed in statusThread. If there is a problem creating the thread, the error code can be found by calling GetLastError.

The status thread starts by sending an AT+CSQ signal (which means "give me the RSSI value") to the modem and waits for a response. Although this is a synchronous function call (in other words, it will wait on the return), the Mobility Client can continue working on its own thread. If the returned value is a known error code, such as 99, which means signal unknown, then it is handled appropriately. The state is then calculated based on the RSSI. The modem can be in only one of two states: in range or out of range. The RSSI is compared to a predefined threshold; if it is higher than this threshold, it is in range, otherwise, it is out of range. If there has been a change in state since the last check (or if this is the first time the state has been calculated), then the Mobility Client is updated. To do this, the NotifyRange function is called. This process is then repeated regularly until the DLL is terminated.

It's worth noting that while this status DLL will report only one of two states, it is possible for the Mobility Client to report the network in a number of other states, depending on circumstances. For instance, a network may enter a suspended state, regardless of signal strength.

In th example below, a message (of type ART_API_MESSAGE as seen earlier) is created and populated with the result of the range calculation. This is then passed back to the Mobility Client via the callback function, which was provided during initialization.

void UMTS::NotifyRange(bool inRange)
{
	ART_API_MESSAGE msg;
	memset(&msg, '\0', sizeof(ART_API_MESSAGE));

	if (inRange)
		msg.msgId = eMsg_NetworkInRange;
	else
		msg.msgId = eMsg_NetworkOutOfRange;

	m_callback(m_correlator, &msg);


Setting the threshold

You must choose a suitable RSSI threshold over which the device is deemed to be in range. Finding an optimum threshold can require some work and trial and error. Setting a threshold too low will mean that the signal quality has degraded beyond an acceptable point, which will reduce the effectiveness of the wireless connection. Setting a threshold too high, on the other hand, may cause the Mobility Client to select a lower-priority, less efficient network too often. For example, during development we noted that the modem switched automatically from UMTS to GPRS if the signal deteriorated significantly, which caused a noticeable drop in throughput. This was controlled by hardware and couldn't be monitored by the Mobility Client. We had to do some experimentation before we were able to find an optimum threshold, ensuring that the Mobility Client would only select the UMTS network when the signal quality reached an acceptable level.

It might also make sense to make the threshold value user-configurable, perhaps by setting the value in a configuration file referenced by the status DLL. That way, the optimum threshold can be easily maintained.


Reporting capabilities

As mentioned earlier, the status DLL provides certain capabilities that will report their current status when the Mobility Client calls the Status_Request function with an appropriate message.

If the message eMsg_NetworkCapabilities is passed as the argument, the status DLL provides a list of all supported capabilities. The callback function is used again, as with the range notification, to update the Mobility Client, as shown:

void UMTS::NotifyCapabilities(void)
{
	ART_API_MESSAGE *msg;
	eNETWORKCAPABILITIES * pInfo;
	msg = (ART_API_MESSAGE*) new unsigned char[sizeof(ART_API_MESSAGE)+sizeof(eNETWORKCAPABILITIES)];
	memset(msg, '\0', sizeof(ART_API_MESSAGE)+sizeof(eNETWORKCAPABILITIES));
	msg->msgId = eMsg_NetworkCapabilities;

	pInfo = (eNETWORKCAPABILITIES*) ((unsigned char*)msg + sizeof(ART_API_MESSAGE));
	pInfo->capabilities = m_capabilities;
	pInfo->mtuSize = 0;
	pInfo->averageBPS = 0;
	msg->chDataLen = sizeof(eNETWORKCAPABILITIES);

	m_callback(m_correlator, msg);

	delete [ ]msg;
}

A new variable of type ART_API_MESSAGE is created and populated with the capabilities of the status DLL (which are contained in eNETWORKCAPABILITIES as a 32-bit mask). The Maximum Transmission Unit (mtuSize -- the default of 0 is infinite) and the average throughput of the network in bits/second (averageBPS) are also provided.

In addition to receiving notification when the modem moves in and out of coverage, the Mobility Client can also display the current signal strength. This is requested regardless of whether the client is currently in or out of range. The Status_Request function is called as usual with the eMsg_SignalStrength message. Since the RSSI is already being extracted in order to calculate the range state, it is a simple matter of taking the current value and converting this to a percentage. The result is passed back to the Mobility Client through the usual callback function.

The Mobility Client provides a signal strength indicator, which can be displayed on the desktop, as shown below:


Figure 2. Signal strength indicator
Signal strength indicator

Network status can also be displayed, as shown:


Figure 3. Network Status
Network Statusr

In this case, we see that the UMTS modem network has adequate signal strength and is deemed to be in range. The Mobility Client, therefore, reports the network to be active. Should the modem move out of range, the client immediately responds.


Activating the status DLL

To inform the Mobility Client of the new status DLL, the client configuration file needs to be updated. This file, artour.ini, is located in the Mobility Client installation directory (the default for desktop Windows is c:\Program Files\IBM\Mobility Client). Open this file in a text editor and find the appropriate connection. Locate the StatusDLL property and change it to include the name of the DLL file, as shown below. Then place a copy of the DLL in the same directory, along with any other files that are required by the DLL (such as the modem libraries).

<status.dll>
SectionType=CONNECTION


<ConnInt37> NetworkDLL=artpip.dll InterfaceDescription=internet.3G-GPRS

StatusDLL=ModemStatus.dll

The connection name, in this case, is status.dll, and the InterfaceDescription property refers to the UMTS modem. Further down, the StatusDLL property has been modified to refer to the status DLL file, ModemStatus.dll.


Conclusion

By extending the Mobility Client through the use of a status DLL, you can work around device driver limitations. This article described how to build additional capabilities into the Mobility Client for extracting signal strength information from the modem to effectively manage the network connections. When the modem moves out of radio range, or when the signal becomes so weak that the UMTS connection is no longer efficient, the Connection Manager is able to respond and roam to another network as required.


Resources

About the author

Author photo: Stephen Pipes

Stephen Pipes is an IT Specialist at IBM's Hursley Park Labs in the UK, where he is a member of the Pervasive Computing group, providing consultancy services for customers in Europe, the Middle East, and Africa. Stephen is an expert in WebSphere Application Server security and regularly presents at technical conferences on the subjects of pervasive computing, security, and Java.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=84619
ArticleTitle=Developing a WebSphere Everyplace Connection Manager Status DLL
publish-date=06082005
author1-email=pipessd@uk.ibm.com
author1-email-cc=crothemi@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers