using the windows driver framework to build better drivers n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Using the Windows Driver Framework to build better drivers PowerPoint Presentation
Download Presentation
Using the Windows Driver Framework to build better drivers

Loading in 2 Seconds...

play fullscreen
1 / 44

Using the Windows Driver Framework to build better drivers - PowerPoint PPT Presentation


  • 615 Views
  • Uploaded on

HW-328T. Using the Windows Driver Framework to build better drivers. Peter Wieland WDF Team Technical Lead Microsoft Corporation. Agenda. Types of drivers in Windows Challenges to writing a quality d river How the Windows driver framework (WDF) helps Takeaways

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Using the Windows Driver Framework to build better drivers' - abiola


Download Now An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
using the windows driver framework to build better drivers
HW-328T

Using the Windows Driver Framework to build better drivers

Peter Wieland

WDF Team Technical Lead

Microsoft Corporation

agenda
Agenda
  • Types of drivers in Windows
  • Challenges to writing a quality driver
  • How the Windows driver framework (WDF) helps
  • Takeaways
    • Know how the WDF will help you deliver a great driver for a great customer experience
your customers won t notice a great device driver
Your customers won’t notice a great device driver
  • ,but they’ll certainly notice if it isn’t.
types of driver m odels
Types of driver models

Full Driver

Mini Driver

Driver Code

I/O Handling

Power

Plug & Play

Boilerplate

I/O Handling

Boilerplate

Microsoft Code

Programming Device

Programming Device

Talking to HW

Talking to HW

Miniport Driver

Class Driver

Power

Plug & Play

I/O Handling

Power

I/O Handling

Power

Plug & Play

Boilerplate

Plug & Play

Boilerplate

Programming Device

Programming Device

Talking to HW

Talking to HW

anatomy of a full windows driver
Anatomy of a full Windows driver

Windows Driver Model (WDM)

Driver Code

Microsoft Code

I/O Handling

Power

Plug & Play

Boilerplate

Driver

Programming Device

Talking to Hardware

Hardware (or another driver)

anatomy of a wdf driver
Anatomy of a WDF driver

Windows Driver Model (WDM)

Driver Code

Microsoft Code

I/O Handling

Power

Plug & Play

Boilerplate

Driver

Programming Device

Talking to Hardware

Hardware (or another driver)

wdf for kernel m ode d rivers
WDF for kernel mode drivers
  • Kernel Mode Framework (KMDF) provides
    • Composablebuilding blocks
    • Default behaviors
    • Consistent interfaces & development patterns
  • Start simple, opt into complexity as required
  • WDF doesn’t wrap everything
    • Interfaces focus on common driver scenarios
    • Can escape to WDM if needed
wdf for user m ode d rivers
WDF for user mode drivers

User Mode Host

  • User Mode Framework (UMDF) is most of KMDF but in user-mode
  • Simpler, more familiar development environment for new driver developers
  • User is isolated from driver crashes or security breaches
    • Developer is isolated from crashes too
  • Supported for many peripheral devices

I/O Handling

Power

Plug & Play

Device Specific Code

(i.e. Driver)

Talking to Hardware

Kernel

WDM

Hardware

simple little d river
Simple little driver
  • Fully functional driver
    • Could install this on any USB device
  • Full Plug & Play support
  • Full power management
  • Written using KMDF
simplelittledriver sys
SimpleLittleDriver.sys
  • #include <wdk.h>
  • #include <wdf.h>
  • DRIVER_INITIALIZE DriverEntry;
  • EVT_WDF_DRIVER_DEVICE_ADD OnDeviceAdd;
  • NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,
  • PUNICODE_STRING RegistryPath) {
  • WDF_DRIVER_CONFIG config;
  • WDF_DRIVER_CONFIG_INIT(&config, OnDeviceAdd);
  • return WdfDriverCreate(DriverObject,
  • RegistryPath,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • &config,
  • WDF_NO_HANDLE);
  • }
  • NTSTATUS OnDeviceAdd(WDFDRIVER Driver,
  • PWDFDEVICE_INIT DeviceInit) {
  • return WdfDeviceCreate(&DeviceInit,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • WDF_NO_HANDLE);
  • }
simplelittledriver sys1
SimpleLittleDriver.sys
  • #include <wdk.h>
  • #include <wdf.h>
  • DRIVER_INITIALIZE DriverEntry;
  • EVT_WDF_DRIVER_DEVICE_ADD OnDeviceAdd;
  • NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,
  • PUNICODE_STRING RegistryPath) {
  • WDF_DRIVER_CONFIG config;
  • WDF_DRIVER_CONFIG_INIT(&config, OnDeviceAdd);
  • return WdfDriverCreate(DriverObject,
  • RegistryPath,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • &config,
  • WDF_NO_HANDLE);
  • }
  • NTSTATUS OnDeviceAdd(WDFDRIVER Driver,
  • PWDFDEVICE_INIT DeviceInit) {
  • return WdfDeviceCreate(&DeviceInit,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • WDF_NO_HANDLE);
  • }

Called when driver loads

simplelittledriver sys2
SimpleLittleDriver.sys
  • #include <wdk.h>
  • #include <wdf.h>
  • DRIVER_INITIALIZE DriverEntry;
  • EVT_WDF_DRIVER_DEVICE_ADD OnDeviceAdd;
  • NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,
  • PUNICODE_STRING RegistryPath) {
  • WDF_DRIVER_CONFIG config;
  • WDF_DRIVER_CONFIG_INIT(&config, OnDeviceAdd);
  • return WdfDriverCreate(DriverObject,
  • RegistryPath,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • &config,
  • WDF_NO_HANDLE);
  • }
  • NTSTATUS OnDeviceAdd(WDFDRIVER Driver,
  • PWDFDEVICE_INIT DeviceInit) {
  • return WdfDeviceCreate(&DeviceInit,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • WDF_NO_HANDLE);
  • }

Callback for when driver is attached to a device

simplelittledriver sys3
SimpleLittleDriver.sys
  • #include <wdk.h>
  • #include <wdf.h>
  • DRIVER_INITIALIZE DriverEntry;
  • EVT_WDF_DRIVER_DEVICE_ADD OnDeviceAdd;
  • NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,
  • PUNICODE_STRING RegistryPath) {
  • WDF_DRIVER_CONFIG config;
  • WDF_DRIVER_CONFIG_INIT(&config, OnDeviceAdd);
  • return WdfDriverCreate(DriverObject,
  • RegistryPath,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • &config,
  • WDF_NO_HANDLE);
  • }
  • NTSTATUS OnDeviceAdd(WDFDRIVER Driver,
  • PWDFDEVICE_INIT DeviceInit) {
  • return WdfDeviceCreate(&DeviceInit,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • WDF_NO_HANDLE);
  • }

Use configuration to make a “driver object”

simplelittledriver sys4
SimpleLittleDriver.sys
  • #include <wdk.h>
  • #include <wdf.h>
  • DRIVER_INITIALIZE DriverEntry;
  • EVT_WDF_DRIVER_DEVICE_ADD OnDeviceAdd;
  • NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,
  • PUNICODE_STRING RegistryPath) {
  • WDF_DRIVER_CONFIG config;
  • WDF_DRIVER_CONFIG_INIT(&config, OnDeviceAdd);
  • return WdfDriverCreate(DriverObject,
  • RegistryPath,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • &config,
  • WDF_NO_HANDLE);
  • }
  • NTSTATUS OnDeviceAdd(WDFDRIVER Driver,
  • PWDFDEVICE_INIT DeviceInit) {
  • return WdfDeviceCreate(&DeviceInit,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • WDF_NO_HANDLE);
  • }

Callback when Windows assigns the driver to a device

simplelittledriver sys5
SimpleLittleDriver.sys
  • #include <wdk.h>
  • #include <wdf.h>
  • DRIVER_INITIALIZE DriverEntry;
  • EVT_WDF_DRIVER_DEVICE_ADD OnDeviceAdd;
  • NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,
  • PUNICODE_STRING RegistryPath) {
  • WDF_DRIVER_CONFIG config;
  • WDF_DRIVER_CONFIG_INIT(&config, OnDeviceAdd);
  • return WdfDriverCreate(DriverObject,
  • RegistryPath,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • &config,
  • WDF_NO_HANDLE);
  • }
  • NTSTATUS OnDeviceAdd(WDFDRIVER Driver,
  • PWDFDEVICE_INIT DeviceInit) {
  • return WdfDeviceCreate(&DeviceInit,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • WDF_NO_HANDLE);
  • }

Create a “Device Object” for this driver and add it to the driver stack

simplelittledriver sys6
SimpleLittleDriver.sys
  • #include <wdk.h>
  • #include <wdf.h>
  • DRIVER_INITIALIZE DriverEntry;
  • EVT_WDF_DRIVER_DEVICE_ADD OnDeviceAdd;
  • NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,
  • PUNICODE_STRING RegistryPath) {
  • WDF_DRIVER_CONFIG config;
  • WDF_DRIVER_CONFIG_INIT(&config, OnDeviceAdd);
  • return WdfDriverCreate(DriverObject,
  • RegistryPath,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • &config,
  • WDF_NO_HANDLE);
  • }
  • NTSTATUS OnDeviceAdd(WDFDRIVER Driver,
  • PWDFDEVICE_INIT DeviceInit) {
  • return WdfDeviceCreate(&DeviceInit,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • WDF_NO_HANDLE);
  • }
  • Less than 25 lines of code
  • Minimal boilerplate
  • Minimal cleanup code
tracking memory u se
Tracking memory use
  • Drivers are very dynamic, lots of state to track & cleanup
    • State of device, client requests, background work, etc…
  • Error handling adds to clean-up work
  • Becomes difficult to keep up with
  • Drivers share address space
    • Proper management is critical
  • WDF automates much of this through objects
wdf objects
WDF objects
  • WDF objects help driver manage its state & allocations
    • WDF objects make up the WDF API
    • WDF knows the lifetime of many objects, deletes automatically
  • Object context
    • Space for driver to store its own data
    • Freed with the object
    • Object events to help with clean-up
  • Object parents & children
    • Can override default object parent
    • Deleting an object deletes the children
adding driver s state data
Adding Driver’s State & Data
  • structDeviceContext {
  • MYDEVICE_STATE CurrentState;
  • ...
  • };
  • WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DeviceContext,
  • GetDeviceContext);
  • NTSTATUS OnDeviceAdd(...) {
  • WDFDEVICE device;
  • DeviceContext* context;
  • WDF_OBJECT_ATTRIBUTES attributes;
  • WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes,
  • DeviceContext);
  • attributes.EvtDestroyCallback= OnDeviceDestroy;
  • WdfDeviceCreate(&DeviceInit, &attributes, &device);
  • if (failure) {return status;}
  • deviceContext = GetDeviceContext(device);
  • deviceContext->CurrentState = MyDeviceStateUninitialized;
  • ...
  • }
  • Set a callback to free memory allocated for the device
  • Declare the structure to be an object context type. GetDeviceContext will get it from the object
  • Get the context off the new object & initialize it
  • Initialize object attributes structure with the new context type
  • Supply object attributes when creating device
  • Define a structure to hold driver’s private data for the Device
creating child objects
Creating Child Objects
  • NTSTATUS OnDeviceAdd(...) {
  • WdfUsbTargetCreate(device,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • &deviceContext->UsbIoTarget);
  • if (failure) return status;
  • WDF_OBJECT_ATTRIBUTES attributes;
  • WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes,
  • RequestContext);
  • attributes.ParentObject = deviceContext->UsbIoTarget;
  • WdfRequestCreate(&attributes,
  • deviceContext->UsbIoTarget,
  • &deviceContext->UsbRequest);
  • if (failure) return status;
  • InitializeRequestContext(deviceContext->UsbRequest);
  • if (failure) return status;
  • ...
  • }
  • WDF deletes Driver and Device Objects automatically on failure or during removal/unload
  • Which deletes the USB Target
  • Which deletes the Request
  • Make a Request as a child of the USB Target
  • Create Request
  • Make a USB Target as a child of the device (default parent)
handling i o operations
Handling I/O operations
  • Clients can open SimpleLittleDriver but can’t send I/O
    • SimpleLittleDriver doesn’t register any I/O handlers
  • Challenges for I/O handling are:
    • Asynchronous execution
    • Concurrency
    • Validation
    • Cancellation
    • Clean-up
  • WDF drivers handle I/O with queue and request objects
i o queues
I/O queues
  • Queues coordinate flow of requests within the driver
  • Driver can use multiple queues to collect or distribute work
  • Can dispatch requests one at a time or in parallel
  • WDF presents all I/O through the top level queues
  • Can use queues as gates to stop and restart I/O flow
request objects
Request objects
  • Packets of work from a client
    • Packets support asynchronous I/O
  • Driver can add context/children to track state & clean-up
  • Simplify validation of parameters/payload
  • Help manage race conditions between delivery, cancellation & completion
registering an i o callback

Dispatch requests one at a time

  • Make this the device’s default Queue
  • Creating an I/O Queue starts with the Object configuration
Registering an I/O Callback
  • NTSTATUS OnDeviceAdd(…, PWDFDEVICE_INIT DeviceInit) {
  • ...
  • // After creating the device…
  • WDF_IO_QUEUE_CONFIG queueConfig;
  • WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
  • &queueConfig,
  • WdfIoQueueDispatchSequential
  • );
  • queueConfig.EvtIoDeviceControl = OnDeviceControl;
  • WdfIoQueueCreate(device,
  • &queueConfig,
  • WDF_NO_OBJECT_ATTRIBUTES,
  • WDF_NO_OBJECT);
  • }
  • Add handler for device control Requests
  • Create the Queue (child of Device)
device control handler

Complete the request on any errors. Request completion will trigger deletion.

Device Control Handler
  • VOID OnDeviceControl(WDFQUEUE Queue, WDFREQUEST Request,
  • size_tInputCb, size_tOutputCb,
  • ULONG IoControlCode) {
  • if (IoControlCode != IOCTL_MYDRIVER_DO_SOMETHING) {
  • goto error;
  • }
  • WdfRequestRetrieveInputBuffer(Request,
  • sizeof(DO_SOMETHING_INPUT),
  • &input,
  • NULL);
  • if (failure) goto error;
  • // Validate input structure
  • if (failure) goto error;
  • // Start request running.
  • if (failure) goto error;
  • return;
  • Error:
  • WdfRequestComplete(Request, status);
  • return;
  • Get the input buffer, which contains parameters from the client
  • Require input to be at least this size (simplifies validation)
  • Make sure all the input parameters are valid.
  • Kick off the request processing asynchronously (for very short requests, work can be done synchronously)
  • Return the thread to the client. Some async callback later will trigger request completion.
  • Device only supports one IOCTL
  • Handler for a device-specific operation (aka I/O control or IOCTL)
handling concurrency
Handling concurrency
  • Use queues to serialize requests
    • Use parallel queues to distribute work to sub-queues
    • Use sequential/manual queues to collect work & protect shared resources (hardware, data, etc…)
  • Use locks to coordinate between I/O and other work
    • WaitLock or SpinLock Objects, or WdfObjectLockmethod
  • Limit blocking (including locks) in I/O paths
    • Ties up client’s threads & increases system latency
saving power
Saving power
  • Power management is critical for that great user experience
  • Windows rules for power are very complicated
    • Must be coordinated with PnP and asynchronous I/O
  • Many drivers do it wrong
    • Don’t power off when they aren’t in use, or
    • Don’t handle all the edge cases or concurrency
  • 10% of all driver crashes are related to power management
enabling power m anagement
Enabling power management
  • When creating a device, WDF driver
    • Declares device’s power capabilities
    • Sets power event callbacks
  • WDF’s power state machines control power automatically
    • Handles OS power change requests
    • Calls driver to perform device-specific power actions
    • Power on, power off, arm for wake, etc…
detecting need for power
Detecting need for power
  • Driver can set queue’s PowerManaged attribute
  • Power-managed queues coordinate I/O and power for you
    • Holds requests until device is on
    • Starts power up sequence when new requests arrive
  • Use power managed queues when you touch hardware
automatic idle d etection
Automatic idle detection
  • WDF can turn off idle devices automatically
  • Driver sets S0-Idle settings on device
    • Power state to enter
    • Timeout
    • Wake capability
    • System vs. driver managed transitions
  • Device is idle when all power managed queues are idle
  • Driver can stop and restart idle detection
    • To stay on when doing non request based work
power callbacks idle settings
Power Callbacks & Idle Settings
  • NTSTATUS OnDeviceAdd(...) {
  • WDF_PNPPOWER_EVENT_CALLBACKS powerCb;
  • WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&powerCb);
  • powerCb.EvtDeviceD0Entry = OnD0Entry;
  • powerCb.EvtDeviceD0Exit = OnD0Exit;
  • WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit,
  • &powerCb);
  • // create the device ...
  • WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
  • WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(
  • &idleSettings,
  • IdleUsbSelectiveSuspend
  • );
  • idleSettings.IdleTimeout = 500; // milliseconds
  • WdfDeviceAssignS0IdleSettings(device, &idleSettings);
  • if (failure) return status;
  • }
  • After creating the device, setup the idle policy using USB selective suspend to wake (since this is a pretend USB devcice)
  • Setup behavior of device when idle in system working state (S0)
  • Driver can override WDF’s default timeout
  • Set power callbacks before creating the Device
  • OnD0Entry will turn the device on, restore any volatile settings
  • Driver can set PnP/Power callbacks to customize device startup, shutdown & power behaviors
  • OnD0Exit saves the current state of the device and turns it off
windows driver f rameworks
Windows driver frameworks
  • WDF lets you focus on controlling your device, not dealing with the OS
  • KMDF can significantly reduce driver size and complexity
  • UMDF provide a more familiar development environment
  • Both let you build a high-quality driver quickly
what type of driver d o i need
What type of driver do I need?
  • Use Windows class drivers where possible
  • Follow driver model for your device class
    • Use WDF’s support objects in “miniport mode” as-needed
  • For full drivers, use UMDF where possible
  • Use KMDF everywhere else
  • You should never have to write a WDM driver
your customers won t notice a great device driver but they ll certainly notice if it isn t
Your customers won’t notice a great device driver,but they’ll certainly notice if it isn’t.
related sessions
Related sessions
  • [HW-773T] Building great USB 3.0 devices
  • [HW-322T] Designing great devices and drivers
  • [HW-235T] Developing drivers in Visual Studio
  • [HW-907C] Inside the Windows 8 driver developer workflow
  • [HW-721H] Experiencing Windows Driver Kit integration with Visual Studio
further reading and documentation
Further reading and documentation
  • Getting Started:
    • The WDF Book: Developing Drivers with Windows Driver Foundation by Orwick and Smith
      • 50% off coupon code DDWDF
    • Kernel-Mode Driver Framework Design Guide
    • User-Mode Driver Framework Design Guide
    • Choosing a driver model
  • What’s New in Windows Driver Frameworks for Windows 8
  • Contact info – wdfinfo@microsoft.com
  • Blogs - Mine, and others about WDF
feedback and q uestions http forums dev windows com session f eedback http bldw in sessionfeedback
thank you

Feedback and questions http://forums.dev.windows.com

Session feedbackhttp://bldw.in/SessionFeedback

slide43

© 2011 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.

The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. 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 provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.