Sunday, August 17, 2008

WinCE 6.0 : Loading device drivers programmatically

Windows CE drivers typically are built into the OS image itself. They are packaged into the OS through platform.bib and loaded by device manager during system boot up. Configuration of these drivers are kept in the registry through platform.reg.

However there can be instances when we want to load a driver programmatically. And we can do so using ActivateDeviceEx. In order to use ActivateDeviceEx, we would need to populate the registry with the appropriate device driver settings, example below.

ActivateDeviceEx
----------------

// prepare registry entries for loading device driver
DWORD ret;
HKEY hkResult;
DWORD dwDisposition;

ret = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
TEXT("Drivers\\BuiltIn\\BTH"),
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hkResult,
&dwDisposition);

TCHAR prefix[] = TEXT("BTH");
TCHAR dll[] = TEXT("\\Nand Disk\\Bluetooth\\Bth_Drv.dll");
DWORD index = 1;

ret = RegSetValueEx(hkResult,
TEXT("Index"),
0,
REG_DWORD,
(BYTE*)&index,
sizeof(index));
ret = RegSetValueEx(hkResult,
TEXT("Dll"),
0,
REG_SZ,
(BYTE*)dll,
sizeof(dll));
ret = RegSetValueEx(hkResult,
TEXT("Prefix"),
0,
REG_SZ,
(BYTE*)prefix,
sizeof(prefix));

RegCloseKey(hkResult);

// load device driver DLL using ActivateDeviceEx
HANDLE hBthDevice = INVALID_HANDLE_VALUE;

hBthDevice = ActivateDeviceEx(TEXT("Drivers\\BuiltIn\\BTH"), NULL, 0, NULL);

Sunday, August 3, 2008

WinCE 6.0 : Communication between device driver and application

I was doing a stream interface device driver development on Windows CE 6.0 when I came across a requirement that the typical stream interface device driver is unable to provide. What I am missing is a way for the device driver to notify the application of events within the device driver. After some searching in the internet and MSDN, I came across an API, DuplicateHandle, which is able to help me achieve what I needed.

Application
-----------
1. Create an event in the application.

HANDLE g_hALPS_Event;
g_hALPS_Event = CreateEvent(NULL, FALSE, FALSE, NULL);


2. Send the event handle down to the driver using DeviceIoControl call.

DWORD BytesReturned;
DeviceIoControl(g_hBthDll, IOCTL_BTH_REG_ALPS_EVENT, g_hALPS_Event, sizeof(g_hALPS_Event), NULL,
0, &BytesReturned, NULL);


3. Wait for the event object to be signaled.

while(TRUE)
{
WaitForSingleObject(g_hALPS_Event, INFINITE);
}


Device Driver
-------------
1. Declare a device driver side handle.

HANDLE g_hBTH_Event;


2. Define the IOCTL codes.

#define FILE_DEVICE_BTH 12341234
#define REG_ALPS_EVENT 0x000
#define IOCTL_BTH_REG_ALPS_EVENT CTL_CODE(FILE_DEVICE_BTH, REG_ALPS_EVENT, METHOD_BUFFERED,
FILE_ANY_ACCESS)


3. Within the device driver IOControl routine, use DuplicateHandle on the application handle that was passed down.

HANDLE hCallerProc = 0;
HANDLE hCurrentProc = 0;
hCallerProc = GetCallerProcess();
hCurrentProc = GetCurrentProcess();

switch (dwIoControlCode)
{
case IOCTL_BTH_REG_ALPS_EVENT:
g_hBTH_Event = (HANDLE)pBufIn;
DuplicateHandle(hCallerProc, (HANDLE)pBufIn, hCurrentProc, &g_hBTH_Event,
0, FALSE, DUPLICATE_SAME_ACCESS);
break;
}


4. Whenever the driver needs to notify the application, we would use the SetEvent API.

SetEvent(g_hBTH_Event);