resources allocated during the previous XXX_Open call. | |
XXX_PowerUp | Device Manager calls this function when the operating system comes out of a low power mode. Applications do not call this function. This function executes in kernel mode, can therefore not call external APIs, and must not be paged out because the operating system is running in single-threaded, non-paged mode. Microsoft recommends that drivers implement power management based on Power Manager and power management IOCTLs for suspend and resume functionality in a driver. |
XXX_PowerDown | Device Manager calls this function when the operating system transitions into suspend mode. Similar to XXX_PowerUp, this function executes in kernel mode, can therefore not call external APIs, and must not be paged out. Applications do not call this function. Microsoft recommends that drivers implement power management based on Power Manager and power management IOCTLs. |
In the function names, the prefix
Device Driver Context
Device Manager supports context management based on device context and open context parameters, which Device Manager passes as DWORD values to the stream driver with each function call. Context management is vital if a driver must allocate and deallocate instance-specific resources, such as blocks of memory. It is important to keep in mind that device drivers are DLLs, which implies that global variables and other memory structures defined or allocated in the driver are shared by all driver instances. Deallocating the wrong resources in response to an XXX_Close or XXX_Deinit call can lead to memory leaks, application failures, and general system instabilities.Stream drivers can manage context information per device driver instance based on the following two levels:
1. Device context The driver initializes this context in the XXX_Init function. This context is therefore also called the Init Context. Its primary purpose is to help the driver manage resources related to hardware access. Device Manager passes this context information to the XXX_Init, XXX_Open, XXX_PowerUp, XXX_PowerDown, XXX_PreDeinit and XXX_Deinit functions.
2. Open context The driver initializes this second context in the XXX_Open function. Each time an application calls CreateFile for a stream driver, the stream driver creates a new open context. The open context then enables the stream driver to associate data pointers and other resources with each opened driver instance. Device Manager passes the device context to the stream driver in the XXX_Open function so that the driver can store a reference to the device context in the open context. In this way, the driver can retain access to the device context information in subsequent calls, such as XXX_Read, XXX_Write, XXX_Seek, XXX_IOControl, XXX_PreClose and XXX_Close. Device Manager only passes the open context to these functions in the form of a DWORD parameter.
The following code listing illustrates how to initialize a device context for a sample driver with the driver name SMP (such as SMP1:):
DWORD SMP_Init(LPCTSTR pContext, LPCVOID lpvBusContext) {
T_DRIVERINIT_STRUCTURE *pDeviceContext = (T_DRIVERINIT_STRUCTURE *)
LocalAlloc(LMEM_ZEROINIT|LMEM_FIXED, sizeof(T_DRIVERINIT_STRUCTURE));
if (pDeviceContext == NULL) {
DEBUGMSG(ZONE_ERROR,(L' SMP: ERROR: Cannot allocate memory '
+ 'for sample driver's device context.
'));
// Return 0 if the driver failed to initialize.
return 0;
}
// Perform system intialization...
pDeviceContext->dwOpenCount = 0;
DEBUGMSG(ZONE_INIT,(L'SMP: Sample driver initialized.
'));
return (DWORD)pDeviceContext;
}
Building a Device Driver
To create a device driver, you can add a subproject for a Windows Embedded CE DLL to your OS design, but the most common way to do it is to add the device driver's source files inside the Drivers folder of the Board Support Package (BSP). For detailed information about configuring Windows Embedded CE subprojects, see Chapter 1, 'Customizing the Operating System Design.'
A good starting point for a device driver is A Simple Windows Embedded CE DLL Subproject, which you can select on the Auto-Generated Subproject Files page in the Windows Embedded CE Subproject Wizard. It automatically creates a source code file with a definition for the DllMain entry point for the DLL, various parameter files, such as empty module-definition (.def) and registry (.reg) files, and preconfigures the Sources file to build the target DLL. For more detailed information about parameter files and the Sources file, see Chapter 2, 'Building and Deploying a Run-Time Image.'
Implementing Stream Functions
Having created the DLL subproject, you can open the source code file in Visual Studio and add the required functions to implement the stream interface and required driver functionality. The following code listing shows the definition of the stream interface functions.
// SampleDriver.cpp : Defines the entry point for the DLL application.
//
#include 'stdafx.h'
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD ul_reason_for_call, LPVOID lpReserved) {