Writing a Device Driver
Windows Driver Kit: Windows SideShow
Writing a Device Driver

Windows SideShow-compatible drivers are user-mode drivers that are built against the Microsoft Windows User-Mode Driver Framework (UMDF) and use the Windows SideShow class extension component. The driver is compatible with Windows SideShow if it instantiates an instance of an ISideShowClassExtension interface, registers an ISideShowDriver interface with the class extension object, and then forwards certain input/output controls (IOCTLs) into the class extension object for processing.

Note It is important for developers who want to write Windows SideShow-compatible drivers to become familiar with the UMDF.

Considerations for Writing a Device Driver

It is important to think through the following key questions before you write a driver for Windows SideShow. This process will help as you make various design and implementation decisions while writing the driver.

  • Determine whether the device requires functionality beyond that which is offered by the Windows SideShow platform. Developers have a number of extensibility mechanisms available to customize the driver beyond the general capabilities of the platform.
  • Determine the level of interaction required on the device, and whether it will need to send events back to the platform.
  • Determine the supported data formats. Microsoft defines two primary data formats, the Simple Content Format (SCF) and iCalendar, though device manufacturers may support additional formats as well.
  • Determine the level of user customization of the UI and device behaviors. Adding user-configurable options will likely require the development of associated computer-side UI to change those options.
  • Determine whether the device will maintain a local cache of content.
  • Determine whether the device will operate when the computer is in a sleep or hibernate state.
  • Determine whether certain user-specific data will be persisted in the device or by the driver.

Two Driver Extremes

The level of complexity in a Windows SideShow driver is inversely proportional to the power and capabilities of the device firmware. There are two extremes for driver/firmware combinations—the simple driver and complex device, and the simple device and complex driver. Of course, your specific device implementation may fall somewhere in between.

A text or small bitmap display, such as a display that is attached to a keyboard, may not have enough memory or processing power to perform complex computations, such as generating, formatting, or caching content. In this case, it makes more sense to put the majority of the implementing logic in the driver. For example, to display Windows SideShow content on a keyboard bitmap display, the driver can render glance content, the content that's meant to be seen at a glance, as a bitmap and then just send a bitmap to the device. This maintains the content cache for the device within the driver. The only action of the device itself is to display a simple bitmap, making the firmware implementation very simple.

A more powerful device, such as a mobile phone, can easily perform complex processing on the device. For these devices, the driver passes the data directly to the device and all the work is done on the device itself, making the driver implementation very straightforward.

First Steps: Initialization and Input/Output Control

If you are unfamiliar with writing a user-mode device driver, you may want to refer to Overview of the UMDF.

Note  Many of these concepts and examples are illustrated in the Windows SideShow sample driver in the Windows Driver Kit.

Initializing the Class Extension

The Windows SideShow class extension should be initialized during the UMDF callback. Use the COM CoCreateInstance function to create an instance of the SideShowClassExtension object that exposes the ISideShowClassExtension interface. The object should be created as a COM in-process local object. After the class extension object has been created, the object must be initialized. Initialize the class extension by calling the ISideShowClassExtension::Initialize method on the object, and pass in two parameters as shown in the following method declaration:

HRESULT Initialize(
        [in]    IUnknown* pWdfDeviceUnknown,
        [in]    IUnknown* pSideShowDriverUnknown
        );

The first parameter, pWdfDeviceUnknown, is a pointer to an IWDFDevice object that will be used by the class extension object to interact with the driver framework and to communicate with other Windows SideShow platform components. The class extension object will keep a reference to the IWDFDevice object. This interface is provided by the Windows User-Mode Driver Framework (UMDF) as a parameter to the OnPrepareHardware callback.

The second parameter, pSideShowDriverUnknown, is a pointer to an object that implements the ISideShowDriver interface. This object is created by the driver and implements the Windows SideShow driver interface.

The class extension object should be initialized only once after the driver has loaded. As part of the initialization process, the class extension component handles some common initialization tasks, such as registering and exposing the appropriate Windows SideShow functional device interfaces. Your device will not work with the Windows SideShow platform if the Initialize method does not succeed.

In some rare instances, it might be acceptable not to call the ISideShowClassExtension::Initialize method during driver startup. For example, if your driver operates in a “flashing” or “update” mode (corresponding to your device being in the boot-loader or otherwise not capable of functioning as a Windows SideShow-compatible device), it might expose a separate device interface for that functionality. In that case, you would not want your driver to advertise Windows SideShow functionality, and thus would not call the ISideShowClassExtension::Initialize method on the class extension component.

Handling Device I/O Controls

After the class extension object has been initialized, it is now ready to process commands from the Windows SideShow platform. These commands are sent to the driver as the Windows Portable Device (WPD) input/output controls (IOCTLs). Forwarding IOCTLs into the class extension is straightforward, as shown in the following example code:

HRESULT CMyDevice::ProcessIoControl(
        /* [in] */ IWDFIoQueue*    pQueue,
        /* [in] */ IWDFIoRequest*  pRequest,
        /* [in] */ ULONG           ControlCode,   
        /* [in] */ SIZE_T          InputBufferSizeInBytes,
        /* [in] */ SIZE_T          OutputBufferSizeInBytes,
        /* [out]*/ DWORD*          pcbWritten)
{
     if (m_pClassExtension == NULL)
     {
        return E_UNEXPECTED;
     }

     if (IS_WPD_IOCTL(ControlCode))
     {
          hr = m_pClassExtension->OnProcessIoControl(
                                   pQueue,
                                   pRequest,
                                   ControlCode,
                                   InputBufferSizeInBytes,
                                   OutputBufferSizeInBytes,
                                   pcbWritten);
     }

    return hr;
}

Forwarded WPD IOCTLs will then be processed and broken out into calls on the ISideShowDriver object that was registered with the class extension through the Initialize method.

ISideShowDriver::OnProcessIoControl Method

The ISideShowDriver::OnProcessIoControl method has the same signature as that from UMDF, with the addition of the last out parameter. You can call this method in response to any incoming WPD IOCTLs in the driver (as determined by the IS_WPD_IOCTL() macro). If the class extension cannot handle the forwarded IOCTL, it will return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), or another HRESULT error code.

ISideShowClassExtension::Uninitialize Method

The driver should call the ISideShowClassExtension::Uninitialize method on the class extension object to clean up the class extension before the driver exits. The ISideShowClassExtension::Uninitialize method will release the Windows SideShow functional interfaces and perform other platform-related cleanup.

Next Steps: Implementing the Windows SideShow Driver Interface

The implemented ISideShowDriver object provides the heart of the driver functionality and is registered with the class extension object. The developer implements this interface to receive content from the Windows SideShow platform. For a more detailed discussion about how to implement the interface, see ISideShowDriver.

Final Step: Building an INF File

In addition to the previous steps, you must build a setup information (INF) file, which is the last step that is needed before you can install a driver. An INF file contains information that the installer uses to install the driver. Depending on the device, you will need to customize sections specific to your device.

The INF file matches the Plug and Play hardware ID of your device to the information required to install the driver. For more information about building an INF file for your device, see Building an INF File for a Windows SideShow-Compatible Device.

If you are new to writing an INF file, see INF File Sections and Directives.


Send feedback on this topic
Built on November 19, 2009
Page view tracker