Writing Device Drivers for Microsoft Windows CE

Microsoft Corporation

June 1999

Summary: Describes the process of developing device drivers for Microsoft® Windows® CE. (12 printed pages) Illustrates the device driver architecture, discusses the primary Windows CE device driver models, and identifies associated APIs and design issues.

Contents

Introduction
Introduction to Windows CE Device Drivers
Creating Windows CE Drivers
Developing Native Device Drivers
Developing Stream Interface Drivers
Developing USB Device Drivers
NDIS Drivers
For More Information

Introduction

Microsoft® Windows® CE is a scalable, compact 32-bit operating system. Windows CE is highly modular, offering original equipment manufacturers and independent hardware vendors the opportunity to develop software targeted to their hardware and platform. To help developers take advantage of the customizability inherent in the OS design, this article introduces the process of developing device drivers for Windows CE. It provides an overview of device driver architecture, discusses the primary Windows CE device driver models, and identifies associated APIs and design issues.

Users who have an introductory-level familiarity with the structure of the Windows CE operating system and some previous experience developing software will get the most benefit from this article. For detailed information on developing device drivers, see the Microsoft Windows CE Device Driver Kit (DDK) and the other references cited at the end of this document.

Introduction to Windows CE Device Drivers

A key aspect of the modular design of Windows CE is that original equipment manufacturers (OEMs) and independent hardware vendors (IHVs) can implement device drivers that support their own hardware without additional development from Microsoft. The versatility of Windows CE provides a rich opportunity to develop applications for a wide range of devices, either built-in or installable. Built-in devices are typically integral to a Windows CE-based platform and are designed specifically for low-level, built-in hardware, such as keyboards, display screens, and PC Card sockets. Installable devices are third-party peripheral devices that can be connected to a Windows CE-based platform at any time.

Windows CE provides several models for driver development, including driver models from other operating systems. Driver models are differentiated only by the software interface they support and not by the devices they serve. The model determines the software interface that any given driver exports.

Windows CE supports the following four driver models:

Device Driver Models

A device driver is code that communicates with or simulates the presence of a hardware device. It links the device with the operating system, making the device available to the operating system and applications through an interface. Device drivers can access their devices directly if the devices are mapped into system memory, or they may need to use the services of lower-level drivers—that is, drivers that are closer to the hardware—in order to access their devices.

Windows CE supports four types of drivers: Native, Stream, USB, and NDIS. The characteristics of these models are summarized in the following table.

Device driver type Devices supported Written by Operating Systems Architecture Functionality
Native Devices that have a custom software interface to Windows CE OEMs, Microsoft Windows CE only monolithic or layered Loaded and called by core OS at boot time. Microsoft defines the APIs that form these drivers' interfaces with the rest of the Windows CE operating system.
Stream interface Any device whose I/O operations are similar to the operation of reading and writing to a file OEMs, IHVs, Microsoft Windows CE only monolithic or layered Implements stream interface functions. Loaded by Device Manager at system boot time, device detection time, or application load time; exposed through file system.
Universal Serial Bus (USB) USB-compliant devices OEMs, IHVs, Microsoft Windows CE, Windows NT, Windows 9x layered Loaded by USB Driver module supplied by Microsoft. Exports a variety of functions: stream interface, custom, or Windows CE APIs.
Network Driver Interface Specification (NDIS) Networking protocols such as TCP/IP OEMs, IHVs, Microsoft Windows CE, Windows NT, Windows 9x layered Presents APIs to networking protocol stacks and network interface cards (NICs).

Device Driver Architecture

Any device driver in Windows CE can conform to a monolithic or layered organizational model.

A monolithic device driver has the following characteristics:

A layered device driver has the following characteristics:

Distinctions between these two layers are described in the following table.

Layer Characteristics
MDD (upper layer)
  • Closer to OS.

  • Accesses its devices indirectly, through the PDD layer.

  • Common to all platforms and functions both as source code and as a library.

  • Links to PDD layer and defines the DDSI functions to be called in PDD layer.

  • Implements its DDI, a set of functions called by the Graphics, Windowing, and Events Subsystem (GWES) module or the FileSys component.

  • Provided by Microsoft. If customized, the MDD layer must be maintained and supported by the developer.
PDD (lower layer)
  • Closer to hardware.

  • Hardware dependent; typically must be customized and ported to platform hardware.

  • Interfaces with MDD and hardware.

  • Implements the DDSI functions called by the MDD layer.

  • Functions implement discrete tasks that the MDD uses to achieve its goals; there is no direct one-to-one relationship between the functions in a PDD and the corresponding MDD.

  • Sample PPD layers are provided by Microsoft for a range of devices.

The following diagram illustrates the integration of monolithic and layered device drivers within the Windows CE operating system.

Each device driver model has advantages in the context of the overall design considerations. Many of the sample drivers provided by Microsoft use the layered organization because it reduces the amount of code that developers must write when porting the sample drivers to new devices. In some instances, however, a monolithic driver might be a better choice than a layered driver. If performance is a critical factor, for example, using a monolithic driver avoids the overhead associated with the function calls that take place between the MDD and PDD layers. A developer might also choose to implement a monolithic driver if the capabilities of the target device correspond closely to the tasks performed by the functions in the MDD layer.

Not all devices built into a Windows CE–based platform are served by native device drivers; some devices, such as built-in audio hardware, are served by stream interface drivers.

The Device Manager

The Device Manager is a user-level process that is typically loaded at boot time on a Windows CE–based platform. It is an application that interacts with the kernel, registry, file system, and most device driver dyamic-link libraries (DLLs).

The Device Manager performs the following tasks:

Creating Windows CE Drivers

The process of writing a Windows CE device driver will vary greatly in detail, depending on which of the four types of drivers—Native, Stream, USB, or NDIS—that you are implementing. Microsoft provides many resources to support this process, including numerous sample device drivers, copious documentation, and native and remote debugging tools.

Creating a generalized driver in Windows CE entails the following steps:

  1. Identify the interface between the driver and the device.
  2. Identify the APIs that the driver needs to expose.
  3. Identify any additional interfaces that the device driver must use, such as operating system services.

  4. Determine an appropriate mapping between the interfaces. This is the essence of a device driver's job: mapping between the functions that applications or the operating system will call in the driver and the functionality provided by the device itself.

  5. Identify any additional architectural factors that are relevant to your device driver, such as whether it must be organized as specific modules and what functions are likely to have the most time or memory constraints.

  6. Identify any preexisting code that you can borrow or port.

  7. Implement any remaining code.

  8. Test and debug the device driver.

Developing Native Device Drivers

Native device drivers serve types of devices for which Microsoft has designed a specific API set. Such devices are typically integral to a Windows CE–based platform and are generally built into a Windows CE-based platform's hardware. They are designed specifically for low-level built-in hardware, such as batteries, keyboards, screens, and PC Card sockets. Native device drivers are always loaded when the Windows CE–based platform boots.

Microsoft provides support for native device drivers in the form of custom interfaces, so IHVs do not need to write native device drivers. However, OEMs must port Microsoft's native device drivers to their hardware or write their own native device drivers from scratch in order to customize Windows CE for new platforms.

Architecture of Native Device Drivers

Platform Builder includes sample native device drivers for both monolithic and layered drivers. Most native device drivers, however, are configured as layered device drivers.

Native device drivers present a standard set of functionality for all devices of a particular class, and all representatives of a specific class conform to the same interface. This enables the Windows CE operating system to treat all instances of a particular device class similarly. For example, the operating system treats both RS-232C ports and infrared ports as serial ports even though the two ports behave differently, because the serial port device driver hides the differences from the operating system.

Typically, OEMs link native device drivers with the GWES module when they build custom Windows CE–based platforms, although there are exceptions. For example, users install and load some types of native device drivers, such as secondary display drivers and printer drivers. If the target devices are reasonably similar to those supported by the samples in the Windows CE Platform Builder, the developer has the option of porting the sample native device drivers to the target platform—an approach that can save time and reduce bugs.

Interrupt Handling in Native Device Drivers

Windows CE uses interrupts to signal when a device needs servicing by its driver. Windows CE does not currently support nested interrupts; processing of one interrupt must finish before another begins, and additional interrupts are turned off while an interrupt is being processed. To minimize the amount of time during which interrupts are disabled, Windows CE divides interrupt handling into two processes: the kernel-mode interrupt service routine (ISR) and the user-mode interrupt service thread (IST). The ISR determines which interrupt identifier to return to the kernel interrupt handler and coverts the physical interrupt signal into a logical interrupt number, which is processed as a logical interrupt event by the IST.

The ISR is the process that cannot be nested. This restriction is likely to be removed in future versions of Windows CE.

Sample Code for Native Device Drivers

The Windows CE DDK provides many sample native device drivers, and using code from these samples can significantly reduce development time. Provided drivers include:

Developing Stream Interface Drivers

In contrast to native drivers, which have custom interfaces, stream interface drivers expose a generic type of interface to the operating system. The stream interface driver model can therefore be used for any device whose functionality does not fit the native, USB, or NDIS device driver models. Stream interface drivers are DLLs that are typically loaded, controlled, and unloaded by an application called the Device Manager. Stream interface drivers are designed mainly for peripheral devices connected to a Windows CE–based platform. Examples of these devices are modems, printers, and digital cameras.

Stream interface drivers are typically designed by IHVs for peripheral devices. However, OEMs who customize Windows CE–based platforms by adding special built-in devices will write stream interface drivers for those additional built-in devices. For example, a Windows CE–based point-of-sale system might have a bar-code scanner built into the hardware of the system, but because Microsoft has not yet defined a custom interface for bar-code scanners, the device driver for the scanner would be implemented by the OEM as a stream interface driver.

Architecture of Stream Interface Drivers

The primary task of a stream interface driver is to expose the services of a peripheral to applications by presenting the device as a special file in the file system. All stream interface drivers use the same interface and expose a common set of stream interface functions. Applications access stream interface devices through entries in the file system. These files follow a particular naming convention that differentiates the device files from ordinary files. Device file names all consist of three uppercase letters, a digit, and a colon (for example, "COM1:" or "PGR7:"). The OS recognizes these file names and redirects file I/O operations to the appropriate stream interface driver. Thus, a stream interface driver must convert file I/O operations into the relevant read and write actions on the driver's device.

Loading a Stream Interface Driver

Stream interface drivers are loaded in three ways, which are summarized in the following table.

Loading initiated at Loaded by Pertains to
Boot time Device Manager Built-in drivers; for example, serial port and audio drivers.
Detection of peripheral device attached to platform Device Manager Automatically detectable devices; for example, a PC Card, Modem, or USB floppy disk.
Run time Applications Devices that are not automatically detectable; for example, many serial devices.

The Device Manager uses a variety of registry entries in the process of loading and unloading stream interface drivers to ensure that a Plug and Play device is recognized properly. The DDK documentation discusses these registry entries in detail.

Implementing a Stream Interface Driver

A stream interface device driver typically requires both a lower and an upper interface.

Sample Code for Stream Interface Drivers

The Platform Builder includes the following samples.

Sample Description
Pager Card Device driver for the Motorola NewsCard pager
Modem Card Device driver for a PC Card modem
Audio Device driver for an audio device
PC Card Test Device driver for testing PC Cards
Serial Device driver for devices that connect to a serial port

Developing USB Device Drivers

The USB is an external bus architecture for connecting USB-capable peripheral devices to a host computer. USB is a communications protocol that supports serial data transfers between a host system and USB-capable peripherals. USB technology was developed as a solution to the increasing user demands on computers and the need for flexible and easy-to-use peripherals. A number of standard PC peripherals such as keyboards, mice, joysticks, digital cameras, computer telephone integration (CTI), and video conferencing products benefit directly from USB.

Note that the Universal Serial Bus Specification uses the term function to refer to USB-capable peripheral devices. To avoid confusion arising from the term function as it refers to callable units of C or C++ code, Windows CE documentation uses the term USB device.

USB Support in Windows CE

Windows CE supports the host side of the USB architecture, which enables developers to write USB device drivers for any USB peripheral devices. Windows CE does not implement those portions of the USB specification (that is, the function side of the USB architecture) that would allow a Windows CE device itself to act as a USB peripheral to another computer system. In addition, the USB architecture implemented in Windows CE supports loading any type of USB device driver, including class drivers, but Microsoft does not supply any sample class drivers. The OEM or IHV must write the appropriate USB device driver or class driver to control a USB device connected to the Windows CE platform.

Writing USB device drivers is generally fairly easy because the USB infrastructure itself provides a rich set of services for accessing USB peripheral devices. USB device drivers can use high-level data transfer functions to send data to and read data from USB peripherals, and thus the developer can concentrate on writing the code that exposes the USB device to applications. Windows CE supports all four types of data transfer defined in the Universal Serial Bus Specification. USB device drivers can use any of the transfer types that are appropriate for their peripherals.

Choosing Design Strategies for USB Device Drivers

USB device drivers exist to make the services of peripheral devices available to applications. Developers of USB devices can choose among the following three strategies to make the services of peripheral devices available to applications:

Sample Code for USB Device Drivers

Platform Builder contains sample source code for the following:

NDIS Drivers

The NDIS is the mechanism by which Windows CE supports network connectivity. NDIS provides a pair of abstraction layers used to connect networking drivers to protocol stacks, such as TCP/IP and IrDA, and to network adapters, such as Ethernet cards. NDIS presents two sets of APIs for writers of network drivers: One set interfaces to the networking protocol stacks, and one set interfaces to Network Interface Cards (NICs).

Windows CE 2.0 and later implements a subset of the NDIS 4.0 model used by the Windows NT operating system, enabling OEMs and IHVs to port existing Windows NT networking drivers to Windows CE. The full NDIS supports several types of network drivers, but Windows CE 2.0 and later supports only miniport drivers, not monolithic or full NIC drivers. In addition, note that Ethernet and IrDA are the only NDIS media types supported in Windows CE 2.10.

For miniport drivers, Windows CE is largely source-code compatible with Windows NT; with a few exceptions, Windows CE and Windows NT support identical NDIS APIs. Because full documentation is available in the Windows NT DDK, the documentation for the Windows CE DDK does not discuss at length the process of writing miniport drivers. Microsoft recommends that you adapt a sample miniport driver or port an existing miniport driver from another operating system, such as Windows NT, rather than write one from scratch.

Note that there are several important differences between the Windows CE and Windows NT implementations of NDIS miniports described in the DDK documentation. Microsoft recommends that you review this material carefully before you begin implementing an NDIS driver.

Sample Code for NDIS Drivers

The Windows CE DDK includes the following sample miniport drivers:

For More Information

The information contained in this document represents the current view of Microsoft Corporation on the issues discussed as of the date of publication. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after the date of publication. This document is for informational purposes only.

This White Paper is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS DOCUMENT.

© 1999 Microsoft Corporation. All rights reserved.

Microsoft, Win32, Windows, and Windows NT are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.

Other product and company names mentioned herein may be the trademarks of their respective owners.