5. Device Objects and Driver Roles
Every driver creates one
or more device objects, which represent the driver’s roles in handling
I/O requests and managing its device. KMDF supports the development of
the following types of device objects:
Filter device
objects (filter DOs) represent the role of a filter driver. Filter DOs
“filter,” or modify, one or more types of I/O requests that are targeted
at the device. Filter DOs are attached to the Plug and Play device
stack.
Functional
device objects (FDOs) represent the role of a function driver, which is
the primary driver for a device. FDOs are attached to the Plug and Play
device stack.
Physical
device objects (PDOs) represent the role of the bus driver, which
enumerates child devices. PDOs are attached to the Plug and Play device
stack.
Control
device objects represent a legacy non-Plug and Play device or a control
interface. They are not part of the Plug and Play device stack.
Depending on the design of
the device and the other drivers in the device stack, a driver might
assume one or more of these roles. Each Plug and Play device has one
function driver and one bus driver, but can have any number of filter
drivers. In the Plug and Play device stack, a driver sometimes acts as
the function driver for one device and as the bus driver for the devices
that its device enumerates. For example, a USB hub driver acts as the
function driver for the hub itself and the bus driver for each USB
device that is attached to the hub. Thus, it creates an FDO for the hub
and a PDO for each attached USB device.
5.1. Filter Drivers and Filter Device Objects
A filter driver receives one
or more types of I/O requests that are targeted at its device, takes
some action based on the request, and then passes the request to the
next driver in the stack. Filter drivers do not typically perform device
I/O themselves; instead, they modify or record a request that another
driver satisfies. Device-specific data encryption/decryption software is
commonly implemented as a filter driver.
A filter driver adds a filter DO
to the Plug and Play device stack. A KMDF driver notifies the framework
that it is a filter driver when its device is added to the system, so
that KMDF creates a filter DO and sets the appropriate defaults.
Most filter drivers are not
“interested” in every request that is targeted at their devices; a
filter driver might filter only read requests or only create requests.
To simplify filter driver implementation, KMDF dispatches only the types
of requests that the filter driver specifies and passes all other
requests down the device stack. The filter driver never receives them
and so does not require code to inspect them or pass them to another
driver.
The sample Firefly, Kbfiltr, and Toaster Filter drivers create filter DOs.
KMDF does not support the
development of bus filter drivers. Such drivers are layered immediately
above a bus driver that creates a PDO and add their device objects to
the stack when Plug and Play manager queries the bus driver for bus
relations.
5.2. Function Drivers and Functional Device Objects
Function drivers are the
primary drivers for their devices. A function driver communicates with
its device to perform I/O and typically manages power policy for its
device. In the Plug and Play device stack, a function driver exposes an
FDO.
To support function
drivers, KMDF includes an FDO interface, which defines a set of methods,
events, and properties that apply to FDOs during initialization and
operation. By using the FDO interface, a driver can
Register event callbacks that are related to resource allocation for its device.
Retrieve properties of its physical device.
Open a registry key.
Manage a list of child devices, if the device enumerates one or more children.
When the driver creates its device object, KMDF creates an FDO unless the driver notifies it otherwise.
By default, KMDF assumes that
the function driver is the power policy manager for its device. If the
device supports wake-up signals, the function driver typically also sets
power policy event callbacks to implement this feature. All the sample
drivers, except the KbFiltr and Firefly drivers, create an FDO.
5.3. Bus Drivers and Physical Device Objects
A bus driver typically
operates as the function driver for a parent device that enumerates one
or more child devices. The parent device might be a bus but could also
be a multifunction device that enumerates children whose functions
require different types of drivers. In the Plug and Play device stack, a
bus driver exposes a PDO.
KMDF defines methods, events,
and properties that are specific to PDOs, just as it does for FDOs. By
using the PDO interface, a driver can
Register event callbacks so that the driver can report the hardware resources that its children require.
Register event callbacks that are related to device locking and ejection.
Register event callbacks that perform bus-level operations so that its child devices can trigger a wake signal.
Assign Plug and Play, compatible, and instance IDs to its child devices.
Set removal and ejection relations for its child devices.
Notify the system that a child device has been ejected or surprise removed.
Retrieve and update the bus address of a child device.
Indicate that the driver controls a raw device. (A raw device is driven directly by a bus driver, without a function driver.)
To
indicate that it is a bus driver, a KMDF driver calls one or more of
the PDO initialization methods before creating its device object. If the
driver indicates that it is driving a raw device, KMDF assumes that the
driver is the power policy manager for the device.
Writing bus drivers is much
simpler with KMDF than with WDM. KMDF manages the state of the PDO on
behalf of the driver, so that the driver is only required to notify KMDF
when the device is added or removed. KMDF supports both static and
dynamic models for enumerating child devices. If the status of child
devices rarely changes, the bus driver should use the static model. The
dynamic model supports drivers for devices such as IEEE 1394 buses,
where the status of child devices might change at any time.
For bus drivers, KMDF handles most of the details of enumeration, including:
Reporting children to WDM.
Coordinating scanning for children.
Maintaining the list of children.
In addition, the KMDF interface through which drivers report resource requirements is easier to use than that provided by WDM.
The sample KbFiltr,
OsrUsbFx2/EnumSwitches, and Toaster bus drivers create PDOs and use both
the static and dynamic methods to enumerate their child devices.
5.4. Legacy Device Drivers and Control Device Objects
In addition to Plug and Play
function, bus, and filter drivers, KMDF supports the development of
drivers for legacy devices, which are not controlled by a Plug and Play
lifetime model. Such drivers create control device objects, which are not part of the Plug and Play device stack.
Plug and Play drivers can also use control device objects
to implement control interfaces that operate independently of the
device stack. An application can send requests directly to the control device object, thus bypassing any filtering performed by other drivers in the stack. Such a control device object typically has a queue and might sometimes forward requests from that queue to a Plug and Play device object.
Because control device objects
are not part of the Plug and Play device stack, the driver must notify
KMDF when their initialization is complete. In addition, the driver
itself must delete the device object when the device has been removed
because only the driver knows how to control the lifetime of such a
device. The sample NdisProt, NonPnP, and Toaster Filter drivers create control device objects.