VxWorks USB Driver Development: USBD Architecture and usbdLib API Guide
Developing USB drivers under VxWorks requires a clear understanding of how the USB Device Driver layer, USB Device layer, and Host Controller Driver layer interact.
In the VxWorks USB architecture, the USBD layer provides a hardware-independent abstraction between device drivers and host controller implementations. The usbdLib library exposes a set of generic interfaces for device discovery, configuration, pipe management, data transfers, bus control, and USB host-controller management.
This article continues the USB driver development series by examining the software architecture of VxWorks USB drivers and providing a practical reference for the major functions implemented by usbdLib.
đ USB Driver Software Architecture #
The overall connection structure of USB devices in a computer system is illustrated conceptually in Figure 6.9.
At a functional level, USB has some similarities to a network interface. A network interface primarily provides data transmission, while a USB interface provides both data transmission and device-control capabilities.
From the hardware perspective, a USB Host Controller (HC) can be regarded as a PCI device. The host controller provides the hardware interface through which the computer communicates with external USB devices. In this sense, it performs a role comparable to a Network Interface Card (NIC).
The relationship can be summarized as follows:
| Network Architecture | USB Architecture |
|---|---|
| Network application | USB device driver |
| Network protocol stack | USBD layer |
| Network card driver | HCD layer |
| Network interface hardware | USB Host Controller |
| Network device | USB peripheral |
This hardware similarity also leads to similarities in software architecture.
VxWorks USB driver software is divided into three primary layers:
- Device Driver Layer
- USBD Layer
- HCD Layer
The layers communicate through standardized function interfaces and callbacks.
đ Layered Function Interfaces #
The upper layer invokes functions provided by the lower layer to perform operations. When asynchronous events or transfer completions occur, lower layers notify upper layers through registered callback functions.
The primary interfaces are:
- The USBD layer provides the generic
usbdLibinterface to USB device drivers. - The HCD layer provides the generic
usbHcdLibinterface used by USBD. - The USBD layer provides
pIrp->userCallbackas the primary callback interface for upper-layer clients. - For control pipes,
pUrb->callbackprovides an additional callback mechanism. - The HCD layer uses
pIrp->usbdCallbackto notify the USBD layer of transfer-related events.
This layered structure allows the USB device driver to remain largely independent of the underlying host-controller hardware.
âī¸ USB Interrupt Processing in VxWorks #
A USB peripheral cannot directly generate a traditional processor interrupt through the USB bus. Unlike a conventional interrupt-driven peripheral, USB communication is controlled by the host.
The Host Controller, however, can generate hardware interrupts. These interrupts are routed through the PCI interface into the system’s interrupt infrastructure.
The Host Controller’s interrupt service routine is represented by:
intHandler
The ISR is intentionally kept lightweight. Rather than performing extensive processing directly inside interrupt context, it gives a semaphore associated with:
pHost->intPending
The intThread task waits for this semaphore and performs the actual interrupt processing after receiving it.
Conceptually, the flow is:
USB Host Controller
|
| Hardware Interrupt
v
intHandler
|
| Give semaphore
v
pHost->intPending
|
v
intThread
|
| Process interrupt
v
USB subsystem
This design separates interrupt acknowledgment from more expensive processing. Keeping the ISR short reduces interrupt latency and avoids performing potentially blocking or resource-intensive operations in interrupt context.
đ§Š Understanding the USBD Layer #
The USBD layer acts as an abstraction layer between USB device drivers and host-controller implementations.
The USB specification conceptually represents a USB peripheral as a node. The USBD layer adopts a similar abstraction, allowing upper-layer software to communicate with a USB node without needing to directly understand the underlying host-controller implementation.
The USBD architecture can be divided into two sublayers:
1. Interface Sublayer #
The Interface Sublayer exposes generic APIs to upper-layer clients.
Its primary implementation is:
usbdLib
This is the interface normally used by USB device drivers.
2. Implementation Sublayer #
The Implementation Sublayer contains the core USBD functionality and is primarily implemented through:
usbdCoreLib
The core library already provides a generic function called:
urbExecBlock()
However, directly invoking urbExecBlock() would require upper layers to understand a relatively complex URB interface.
The usbdLib library therefore wraps urbExecBlock() with a collection of simpler, purpose-specific APIs.
The resulting architecture can be viewed as:
USB Device Driver
|
v
usbdLib
|
v
urbExecBlock()
|
v
usbdCoreLib
|
v
HCD
|
v
USB Host Controller
đ ī¸ Core usbdLib Functions #
The following sections summarize the major functions exposed by usbdLib.
1. urbInit #
LOCAL VOID urbInit
(
pURB_HEADER pUrb,
USBD_CLIENT_HANDLE clientHandle,
UINT16 function,
URB_CALLBACK callback,
pVOID userPtr,
UINT16 totalLen
)
urbInit() initializes a URB structure using the supplied parameters.
The resulting URB can then be passed to generic USBD interfaces.
Important parameters include:
- clientHandle â Identifies the registered USBD client.
- function â Specifies the requested USBD operation.
- callback â Callback invoked when URB processing completes.
- userPtr â User-defined pointer associated with the request.
- totalLen â Size of the URB structure, typically
sizeof(USBD_URB).
2. urbCallback #
LOCAL VOID urbCallback
(
pVOID pUrb
)
urbCallback() is used internally by urbExecBlock() as the callback stored in the URB structure when calling usbdCoreEntry().
The usbdCoreEntry() function invokes this callback before returning, allowing synchronous execution to be coordinated through the associated semaphore mechanism.
3. urbExecBlock #
LOCAL STATUS urbExecBlock
(
pURB_HEADER pUrb
)
urbExecBlock() is the central execution mechanism within usbdLib.
It prepares the URB and invokes usbdCoreEntry() to perform processing in the lower USBD layer.
Several implementation details are important.
Semaphore Pool Management #
The semPoolQueue is implemented as a FIFO queue. A task must obtain a semaphore from the queue before invoking usbdCoreEntry().
After processing completes, the semaphore is returned to the queue.
This mechanism limits the number of tasks that can execute usbdCoreEntry() concurrently to:
MAX_SYNCH_SEM
The corresponding initialization is performed by usbdInitialize().
Each queue element represents a semaphore used to synchronize URB completion.
Error-Path Semaphore Handling #
If:
usbdCoreEntry(pUrb) != OK
it may not be possible to determine whether usbdCoreEntry() already executed:
OSS_SEM_GIVE((SEM_HANDLE)((pURB_HEADER)pUrb)->userPtr)
Therefore, the error path uses:
OSS_SEM_TAKE((SEM_HANDLE)msg.lParam, OSS_DONT_BLOCK)
to ensure that the semaphore returns to the state it had before the operation.
The distinction between OSS_DONT_BLOCK and the blocking behavior used during successful execution is important when analyzing this synchronization mechanism.
4. usbdInitialize #
STATUS usbdInitialize (void)
usbdInitialize() initializes the usbdLib subsystem.
The initialization process includes:
-
Creating the
semPoolQueue. -
Initializing a URB with:
urbInit(&urb.header, NULL, USBD_FNC_INITIALIZE, NULL, NULL, sizeof(urb)); -
Calling:
urbExecBlock(&urb.header); -
Completing initialization of
usbdCoreLib.
The semaphore pool created during this stage provides the synchronization infrastructure required for subsequent URB execution.
5. usbdShutdown #
STATUS usbdShutdown (void)
usbdShutdown() performs the reverse operation of usbdInitialize().
The general sequence is:
- Shut down
usbdCoreLib. - Release the resources associated with
semPoolQueue. - Close the underlying OSS library.
When destroying semPoolQueue, the semaphore-management order is important. A semaphore must first be acquired before it can be deleted, and the USB_QUEUE structure referenced by semPoolQueue should only be removed after all associated semaphores have been deleted.
đ¤ Client Registration and Management #
6. usbdClientRegister #
STATUS usbdClientRegister
(
pCHAR pClientName,
pUSBD_CLIENT_HANDLE pClientHandle
)
Registers a client with the USBD subsystem.
Internally, it invokes urbExecBlock() with:
USBD_FNC_CLIENT_REG
The function allocates a USBD_CLIENT structure based on the supplied client name and returns its handle.
7. usbdClientUnregister #
STATUS usbdClientUnregister
(
USBD_CLIENT_HANDLE clientHandle
)
Unregisters a previously registered client.
The function invokes urbExecBlock() using:
USBD_FNC_CLIENT_UNREG
and removes the USBD_CLIENT associated with the supplied handle.
8. usbdMngmtCallbackSet #
STATUS usbdMngmtCallbackSet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_MNGMT_CALLBACK mngmtCallback,
pVOID mngmtCallbackParam
)
Registers a management callback for a client.
The callback allows USBD to notify the client about asynchronous USB management events.
For example, a client may receive notification when a device generates a RESUME signal while the USB bus is suspended.
đ USB Bus Management #
9. usbdBusStateSet #
STATUS usbdBusStateSet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
UINT16 busState
)
Changes the state of the USB bus associated with the specified node.
Typical states include:
SUSPEND
RESUME
The bus is not automatically restored to RESUME after being suspended. A client must explicitly call usbdBusStateSet() with the appropriate resume state.
This behavior is particularly important for USB remote-wakeup processing.
A client can monitor resume-related management callbacks and explicitly resume the bus when required.
Because bus state changes affect all devices and clients using that bus, this function should be used carefully.
10. usbdBusCountGet #
STATUS usbdBusCountGet
(
USBD_CLIENT_HANDLE clientHandle,
pUINT16 pBusCount
)
Returns the number of USB Host Controllers currently attached to the system.
Each Host Controller has its own root hub.
The number of Host Controllers can change dynamically through:
usbdHcdAttach()
usbdHcdDetach()
11. usbdRootNodeIdGet #
STATUS usbdRootNodeIdGet
(
USBD_CLIENT_HANDLE clientHandle,
UINT16 busIndex,
pUSBD_NODE_ID pRootId
)
Returns the nodeId corresponding to the root hub associated with a Host Controller.
busIndex identifies the position of the corresponding USBD_HCD structure within the hcdList linked list.
12. usbdHubPortCountGet #
STATUS usbdHubPortCountGet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID hubId,
pUINT16 pPortCount
)
Returns the number of ports provided by a specified USB hub.
Internally, the operation reaches usbdCoreLib through the fncHubPortCountGet function.
13. usbdNodeIdGet #
STATUS usbdNodeIdGet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID hubId,
UINT16 portIndex,
pUINT16 pNodeType,
pUSBD_NODE_ID pNodeId
)
Retrieves the nodeId associated with the device connected to a particular hub port.
The function can also return the type of node detected at that port.
14. usbdNodeInfoGet #
STATUS usbdNodeInfoGet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
pUSBD_NODE_INFO pNodeInfo,
UINT16 infoLen
)
Retrieves information associated with a USB node.
The information is obtained from the nodeInfo member of the corresponding USBD_NODE structure.
đ Device Attach and Detach Notifications #
15. usbdDynamicAttachRegister #
STATUS usbdDynamicAttachRegister
(
USBD_CLIENT_HANDLE clientHandle,
UINT16 deviceClass,
UINT16 deviceSubClass,
UINT16 deviceProtocol,
USBD_ATTACH_CALLBACK attachCallback
)
Registers a callback for USB device attach and detach events.
The client specifies a device profile using:
- Device class
- Device subclass
- Device protocol
When a matching device is attached or removed, USBD invokes the registered callback.
This mechanism is particularly useful for dynamically detecting devices without continuously polling the USB topology.
16. usbdDynamicAttachUnRegister #
STATUS usbdDynamicAttachUnRegister
(
USBD_CLIENT_HANDLE clientHandle,
UINT16 deviceClass,
UINT16 deviceSubClass,
UINT16 deviceProtocol,
USBD_ATTACH_CALLBACK attachCallback
)
Removes a previously registered dynamic attach/detach callback.
đī¸ USB Feature and Configuration Management #
17. usbdFeatureClear #
STATUS usbdFeatureClear
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
UINT16 requestType,
UINT16 feature,
UINT16 index
)
Clears a USB feature associated with the specified node.
18. usbdFeatureSet #
STATUS usbdFeatureSet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
UINT16 requestType,
UINT16 feature,
UINT16 index
)
Sets a USB feature on the specified device or endpoint.
19. usbdConfigurationGet #
STATUS usbdConfigurationGet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
pUINT16 pConfiguration
)
Retrieves the current configuration associated with a USB device.
The result is returned through pConfiguration.
20. usbdConfigurationSet #
STATUS usbdConfigurationSet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
UINT16 configuration,
UINT16 maxPower
)
Selects a configuration for a USB device.
The maxPower parameter specifies the maximum power expected by the selected configuration.
đ USB Descriptor and Interface Operations #
21. usbdDescriptorGet #
STATUS usbdDescriptorGet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
UINT8 requestType,
UINT8 descriptorType,
UINT8 descriptorIndex,
UINT16 languageId,
UINT16 bfrLen,
pUINT8 pBfr,
pUINT16 pActLen
)
Retrieves a USB descriptor from the specified device.
The parameters identify the request type, descriptor type, descriptor index, and language ID. The descriptor data is returned through pBfr, while pActLen reports the actual amount of data received.
22. usbdDescriptorSet #
STATUS usbdDescriptorSet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
UINT8 requestType,
UINT8 descriptorType,
UINT8 descriptorIndex,
UINT16 languageId,
UINT16 bfrLen,
pUINT8 pBfr
)
Sends descriptor-related data to the USB device.
This interface is provided for USB operations that require descriptor-setting functionality.
23. usbdInterfaceGet #
STATUS usbdInterfaceGet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
UINT16 interfaceIndex,
pUINT16 pAlternateSetting
)
Retrieves the currently selected alternate setting for a USB interface.
24. usbdInterfaceSet #
STATUS usbdInterfaceSet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
UINT16 interfaceIndex,
UINT16 alternateSetting
)
Selects an alternate setting for the specified USB interface.
Alternate settings allow an interface to expose different endpoint configurations depending on the application’s requirements.
25. usbdStatusGet #
STATUS usbdStatusGet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
UINT16 requestType,
UINT16 index,
UINT16 bfrLen,
pUINT8 pBfr,
pUINT16 pActLen
)
Queries the status of a USB device or other USB object.
The returned status data is stored in pBfr, with the actual length reported through pActLen.
đĸ USB Address Management #
26. usbdAddressGet #
STATUS usbdAddressGet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
pUINT16 pDeviceAddress
)
Retrieves the USB address currently assigned to the specified device.
27. usbdAddressSet #
STATUS usbdAddressSet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
UINT16 deviceAddress
)
Assigns a USB device address.
Address management is an important part of USB enumeration and device configuration.
đˇī¸ Vendor-Specific USB Requests #
28. usbdVendorSpecific #
STATUS usbdVendorSpecific
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
UINT8 requestType,
UINT8 request,
UINT16 value,
UINT16 index,
UINT16 length,
pUINT8 pBfr,
pUINT16 pActLen
)
Sends a vendor-specific request through the device’s default control pipe.
USB device manufacturers can define proprietary control requests for functionality that is not covered by standard USB requests.
This interface provides a direct mechanism for device-specific control operations.
đ° USB Pipe Management #
A USB pipe represents the logical communication path between a client and an endpoint.
Before performing normal data transfers, the appropriate pipe must be created.
29. usbdPipeCreate #
STATUS usbdPipeCreate
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
UINT16 endpoint,
UINT16 configuration,
UINT16 interface,
UINT16 transferType,
UINT16 direction,
UINT16 maxPayload,
UINT32 bandwidth,
UINT16 serviceInterval,
pUSBD_PIPE_HANDLE pPipeHandle
)
Creates a USBD_PIPE associated with a particular endpoint.
Important parameters include:
- nodeId â Identifies the target USB device.
- endpoint â Specifies the endpoint used by the pipe.
- configuration â Identifies the relevant USB configuration.
- interface â Identifies the interface associated with the endpoint.
- transferType â Specifies Control, Bulk, Interrupt, or Isochronous transfer.
- direction â Specifies
IN,OUT, orINOUT. - maxPayload â Specifies the maximum endpoint payload.
- bandwidth â Set to
0for Control and Bulk transfers; expressed in bytes per frame for Interrupt transfers and bytes per second for Isochronous transfers. - serviceInterval â Used for Interrupt pipes to specify the maximum service latency in milliseconds.
- pPipeHandle â Receives the newly created pipe handle.
Pipe direction is fixed after creation. INOUT is used specifically for Control pipes.
30. usbdPipeDestroy #
STATUS usbdPipeDestroy
(
USBD_CLIENT_HANDLE clientHandle,
USBD_PIPE_HANDLE pipeHandle
)
Destroys an existing USB transfer pipe.
A pipe should no longer be in use when it is destroyed.
đĄ USB Data Transfer #
31. usbdTransfer #
STATUS usbdTransfer
(
USBD_CLIENT_HANDLE clientHandle,
USBD_PIPE_HANDLE pipeHandle,
pUSB_IRP pIrp
)
Starts a USB transfer on the specified pipe.
The transfer is described by an IRP (I/O Request Packet).
The IRP must be allocated and initialized before calling usbdTransfer().
The general data path is:
USB Device Driver
|
| usbdTransfer()
v
USBD Layer
|
v
HCD
|
v
Host Controller
|
v
USB Bus
|
v
USB Endpoint
32. usbdTransferAbort #
STATUS usbdTransferAbort
(
USBD_CLIENT_HANDLE clientHandle,
USBD_PIPE_HANDLE pipeHandle,
pUSB_IRP pIrp
)
Aborts an active transfer associated with the specified pipe and IRP.
This function is useful when a transfer must be canceled before normal completion.
âąī¸ USB Frame and Isochronous Synchronization #
Isochronous USB applications depend heavily on precise frame timing.
33. usbdSynchFrameGet #
STATUS usbdSynchFrameGet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
UINT16 endpoint,
pUINT16 pFrameNo
)
Retrieves the synchronization frame number associated with an Isochronous endpoint.
If an Isochronous transfer encounters an error, the client can use this information to determine the appropriate starting frame for retransmission or recovery.
The operation corresponds to the USB specification’s synchronization-frame mechanism.
34. usbdCurrentFrameGet #
STATUS usbdCurrentFrameGet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
pUINT32 pFrameNo,
pUINT32 pFrameWindow
)
Returns the current USB frame number associated with the specified node.
If pFrameWindow is valid, the function also returns the maximum scheduling window maintained by the Host Controller.
Because USBD can manage multiple independent Host Controllers, specifying the correct nodeId is essential.
đ SOF Master and Frame Timing Management #
35. usbdSofMasterTake #
STATUS usbdSofMasterTake
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId
)
Requests master-client ownership of the USB bus’s Start-of-Frame timing.
The master client can adjust USB frame timing intervals, which is particularly relevant to Isochronous applications.
Only one master client can control a given USB bus at a time.
36. usbdSofMasterRelease #
STATUS usbdSofMasterRelease
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId
)
Releases SOF master status for the specified USB bus.
Once released, another client can request master status.
37. usbdSofIntervalGet #
STATUS usbdSofIntervalGet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
pUINT16 pSofInterval
)
Retrieves the current Start-of-Frame interval.
The value corresponds to:
pBus->sofInterval
38. usbdSofIntervalSet #
STATUS usbdSofIntervalSet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
UINT16 sofInterval
)
Sets the Start-of-Frame interval stored in:
pBus->sofInterval
Because SOF timing affects the entire USB bus, applications should modify this value only when they have the appropriate bus-management authority.
âšī¸ USBD Version and Host Controller Management #
39. usbdVersionGet #
STATUS usbdVersionGet
(
pUINT16 pVersion,
pCHAR pMfg
)
Returns the version information associated with the USBD implementation.
The version number and descriptive manufacturer string are defined through USBD macros.
40. usbdHcdAttach #
STATUS usbdHcdAttach
(
HCD_EXEC_FUNC hcdExecFunc,
pVOID param,
pGENERIC_HANDLE pAttachToken
)
Registers a Host Controller Driver with the USBD subsystem.
Unlike most usbdLib operations, this function does not require a previously registered USBD_CLIENT_HANDLE.
It is normally used during system initialization to attach one or more HCD implementations.
The function returns an attach token that can later be used by usbdHcdDetach().
41. usbdHcdDetach #
STATUS usbdHcdDetach
(
GENERIC_HANDLE attachToken
)
Removes a previously attached Host Controller Driver from the USBD subsystem.
The token supplied to this function is the one returned by usbdHcdAttach().
đ USB Statistics #
42. usbdStatisticsGet #
STATUS usbdStatisticsGet
(
USBD_CLIENT_HANDLE clientHandle,
USBD_NODE_ID nodeId,
pUSBD_STATS pStatistics,
UINT16 statLen
)
Retrieves USB bus statistics for the specified node.
The statistics are maintained in the corresponding:
pBus->stats
structure.
This interface is useful when diagnosing USB performance, transfer behavior, or bus-level problems during driver development.
đ§ Understanding the Complete usbdLib Data Path #
Although usbdLib exposes many functions, the underlying architecture follows a relatively consistent pattern.
For a typical USB device driver, the sequence is approximately:
1. Register USB client
|
v
2. Detect matching USB device
|
v
3. Obtain node information
|
v
4. Read descriptors
|
v
5. Select configuration/interface
|
v
6. Create required pipes
|
v
7. Allocate and initialize IRPs
|
v
8. Submit USB transfers
|
v
9. Receive completion callbacks
|
v
10. Abort/destroy resources when required
|
v
11. Unregister client
The USBD layer hides much of the hardware-specific complexity from the device driver.
At the upper level, the driver primarily deals with:
- USB nodes
- Clients
- Interfaces
- Endpoints
- Pipes
- IRPs
- Callbacks
- Device configurations
At the lower level, the HCD is responsible for translating these abstract requests into operations understood by the specific Host Controller hardware.
đ Why the Layered Architecture Matters #
The key advantage of the VxWorks USB architecture is separation of responsibilities.
A USB device driver should not need to know whether the underlying Host Controller is implemented using one controller architecture or another. Likewise, an HCD should not need to understand the functional behavior of every USB peripheral connected to the system.
The architecture therefore separates the problem into three major responsibilities:
| Layer | Primary Responsibility |
|---|---|
| Device Driver | Device-specific functionality |
| USBD | Generic USB device abstraction and management |
| HCD | Host-controller hardware and bus scheduling |
This separation makes the USB subsystem easier to port, maintain, debug, and extend.
For example, replacing one Host Controller implementation with another should primarily affect the HCD layer rather than the functional USB device driver.
Likewise, adding support for a new USB peripheral should normally require changes at the device-driver level rather than modifications to the host-controller implementation.
đ Key Takeaways #
The VxWorks USB subsystem is built around a layered architecture in which usbdLib serves as the primary generic interface for USB device drivers.
The most important concepts to remember are:
- USBD abstracts USB hardware from device-specific drivers.
usbdLibprovides simplified interfaces over the lower-levelusbdCoreLib.urbExecBlock()is the central synchronous execution mechanism behind many USBD operations.- Semaphore pooling limits concurrent URB execution and provides synchronization.
- USB device drivers communicate with peripherals through pipes and IRPs.
- Device discovery relies on node IDs, descriptors, configurations, and interfaces.
- Dynamic attach callbacks allow drivers to respond to device insertion and removal.
- The HCD layer isolates Host Controller hardware details from the USBD layer.
- Interrupt processing is split between the lightweight
intHandlerISR and theintThreadtask. - SOF and frame-management APIs are particularly important for time-sensitive Isochronous USB applications.
Understanding these interfaces provides the foundation for analyzing existing VxWorks USB drivers and developing new ones. Once the relationship between the device-driver layer, usbdLib, usbdCoreLib, and the HCD is clear, the implementation details of individual USB drivers become considerably easier to follow.