Software Device API Programming Guide
This guide contains info on how to use the Software Device API to enumerate PnP devices.
Follow this pattern to enumerate a device.
To enumerate a device
- Call SwDeviceCreate to initiate the enumeration of a device. SwDeviceCreate returns a handle that represents the device. PnP enumerates the device for as long as the handle is open. After the device is enumerated, the operating system calls your SW_DEVICE_CREATE_CALLBACK callback function, which is supplied by your client app, to indicate that the device is enumerated. This call to the callback function doesn't indicate that drivers have loaded or started. Through the callback function, your client app is informed of the Device Instance Id of its device.
- After the callback function has been called, your client app can call SwDeviceInterfaceRegister to register device interfaces and can call SwDevicePropertySet, SwDeviceInterfacePropertySet, and SwDeviceInterfaceSetState.
- Your client app calls SwDeviceClose to stop enumeration of the device. PnP will then initiate removal of the device.
- In Windows 8.1 and later, you can call SwDeviceSetLifetime to extend the lifetime of a software device past the lifetime of the open handle. By using the SWDeviceLifetimeParentRemove value, a software device can have its lifetime tied to the enumeration state of its parent. Then, a client app can regain control of the software device by calling SwDeviceCreate and identifying the same device, that is, the same enumerator and instance id.
Keep in mind these items about how the PnP system works. PnP is highly asynchronous and many agents can act on the PnP system in addition to the calls that are being made from a client app to the Software Device API.
- When a client app calls SwDeviceCreate, PnP is informed that the caller wants to enumerate a device but not that the device will be enumerated right away or indeed ever. Administrative policy could prevent the enumeration, or the parent may not be currently enumerated, or this enumeration may be a re-enumeration of the same device that the caller just closed and PnP has not yet removed ("Final Remove") the previous instance. We recommend that you write your client code to not wait on the operating system calling your callback function, but instead take action in response to your callback function being called. In other words, do what you need to do in the callback function itself and don’t block. If you have to block, your wait must be INFINITE. There is no timeout "long enough" here. If there is a problem, blocking indefinitely leads to the best situation to find the problem and debug it.
- Callers of SwDeviceCreate must wait for SW_DEVICE_CREATE_CALLBACK before performing any operations against the device apart from closing the handle.
- The operating system might possibly call SW_DEVICE_CREATE_CALLBACK before the call to SwDeviceCreate returns. For this reason, the software device handle for the device is supplied as a parameter to the callback function.
- By calling SwDeviceClose, you initiate removal of the device, but the call can return before PnP has performed "Final Remove" of the device. If SwDeviceCreate is called again for the same device before "Final Remove" happens, the new create is queued, and the device is enumerated after "Final Remove" happens. Note that "Final Remove" can only happen after all file handles to the device object have been closed. When debugging why a device is not enumerating, the most common cause is that the enumeration has been queued and an open device handle (not to be confused with a software device handle) is preventing "Final Remove."
- The Software Device API feature hides a lot of the complexity that a bus driver would have to deal with from a user mode caller. Just realize that while holding a software device handle open, the device may be removed and re-enumerated by PnP for various reasons but for the most part callers don't care about this.
- A call to your SW_DEVICE_CREATE_CALLBACK callback function doesn't mean that a driver has been loaded and the stack started. Enumeration is only the first step in bringing a device stack up. We recommend that client apps register for device interface arrivals if they need to know when a device’s functionality is usable.
- If a client app needs to set properties and register interfaces, we recommend that it set the properties and register the interfaces every time that it calls SwDeviceCreate. This is best practice because forcing a null driver onto the device by a user or a device driver upgrade can wipe out the property stores.
- There is a subtle difference between properties that are set as part of a SwDeviceCreate or SwDeviceInterfaceRegister call and properties that are later set by calling SwDevicePropertySet or SwDeviceInterfacePropertySet. Properties that are set as part of SwDeviceCreate or SwDeviceInterfaceRegister are stored in memory; if the device is uninstalled or a null driver wipes out the property stores, these properties are written out again by the Software Device API feature when PnP re-enumerates the devices. This is all transparent to the client. Properties that are set using SwDevicePropertySet or SwDeviceInterfacePropertySet after the enumeration don't persist in memory. But, if you set a property by using SwDeviceCreate or SwDeviceInterfaceRegister, you can update the value with SwDevicePropertySet or SwDeviceInterfacePropertySet, and this update is applied to the in-memory value as well as the persisted store.
- SW_DEVICE_CREATE_CALLBACK runs on an arbitrary thread-pool thread.
Note The Software Device API can only be called by Administrators and SYSTEM.