Ⅰ. PS Driver ML-4050N Series PostScript, Driver ML-4050N Series PostScript, Driver.
A simple little driver #include DRIVER_INITIALIZE DriverEntry; EVT_WDF_DRIVER_DEVICE_ADD...
-
Upload
abner-mcdowell -
Category
Documents
-
view
258 -
download
2
Transcript of A simple little driver #include DRIVER_INITIALIZE DriverEntry; EVT_WDF_DRIVER_DEVICE_ADD...
www.buildwindows.com
Using the Windows Driver Framework to build better drivers
Peter WielandWDF Team Technical Lead Microsoft Corporation
HW-328T
www.buildwindows.com
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
www.buildwindows.com
Your customers won’t notice a great device driver
,but they’ll certainly notice if it isn’t.
www.buildwindows.com
Types of driver modelsFull Driver
I/O Handling
Plu
g &
Pla
y
Pow
er
Talking to HW
Boile
rpla
te
Programming Device
Mini Driver
I/O Handling
Talking to HW
Boile
rpla
te
Programming Device
Miniport Driver
I/O Handling
Plu
g &
Pla
y
Pow
er
Talking to HW
Boile
rpla
te
Programming Device
Class Driver
I/O Handling
Plu
g &
Pla
y
Pow
er
Talking to HW
Boile
rpla
te
Programming Device
Microsoft Code
Driver Code
Plu
g &
Pla
y
Pow
er
www.buildwindows.com
Anatomy of a full Windows driver
Hardware (or another driver)
Windows Driver Model (WDM)
I/O Handling
Boilerplate
Plug & Play
Talking to Hardware
PowerProgramming Device
Microsoft Code
Driver Code
Driver
www.buildwindows.com
Anatomy of a WDF driver
Hardware (or another driver)
Windows Driver Model (WDM)
I/O Handling
Boilerplate
Plug & Play
Talking to Hardware
PowerProgramming Device
Microsoft Code
Driver Code
Driver
www.buildwindows.com
WDF for kernel mode drivers
• Kernel Mode Framework (KMDF) provides• Composable building 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
www.buildwindows.com
Kernel
WDF for user mode drivers
• 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
User Mode Host
I/O Handling
Plug & Play
Power
Talking to Hardware
Device Specific Code(i.e. Driver)
Hardware
WDM
A simple little driver
www.buildwindows.com
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#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.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.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.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.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.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.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
Storing Driver Specific Data
www.buildwindows.com
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
www.buildwindows.com
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 & Datastruct DeviceContext { 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; ...}
• Define a structure to hold driver’s private data for the Device
• Initialize object attributes structure with the new context type
• Get the context off the new object & initialize it
• Supply object attributes when creating device
• Declare the structure to be an object context type. GetDeviceContext will get it from the object
• Set a callback to free memory allocated for the device
• WDF deletes Driver and Device Objects automatically on failure or during removal/unload
• Which deletes the USB Target
• Which deletes the Request
Creating Child ObjectsNTSTATUS 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; ...}
• Make a USB Target as a child of the device (default parent)
• Make a Request as a child of the USB Target
• Create Request
Handling I/O
www.buildwindows.com
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
www.buildwindows.com
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
www.buildwindows.com
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 CallbackNTSTATUS 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); …}
• Make this the device’s default Queue
• Add handler for device control Requests
• Dispatch requests one at a time
• Creating an I/O Queue starts with the Object configuration
• Create the Queue (child of Device)
Device Control HandlerVOID OnDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t InputCb, size_t OutputCb, 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;
• Handler for a device-specific operation (aka I/O control or IOCTL)• Device only supports one IOCTL
• 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.
• Complete the request on any errors. Request completion will trigger deletion.
www.buildwindows.com
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 WdfObjectLock method
• Limit blocking (including locks) in I/O paths• Ties up client’s threads & increases system latency
Power Management
www.buildwindows.com
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
www.buildwindows.com
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…
www.buildwindows.com
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
www.buildwindows.com
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
• Set power callbacks before creating the Device
Power Callbacks & Idle SettingsNTSTATUS 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;}
• OnD0Entry will turn the device on, restore any volatile settings
• 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 set PnP/Power callbacks to customize device startup, shutdown & power behaviors• OnD0Exit saves the current state of the device and turns it off
• Driver can override WDF’s default timeout
Summary
www.buildwindows.com
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
www.buildwindows.com
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
www.buildwindows.com
Your customers won’t notice a great device driver,
but they’ll certainly notice if it isn’t.
www.buildwindows.com
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
www.buildwindows.com
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 – [email protected]• Blogs - Mine, and others about WDF
www.buildwindows.com
• Feedback and questions http://forums.dev.windows.com
• Session feedbackhttp://bldw.in/SessionFeedback
thank you
© 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.