USB device model and API for USB device drivers.
More...
|
void | usb_init_xfer_request (struct usb_xfer_request *req) |
|
struct usb_xfer_request * | usb_alloc_xfer_request (uint bufsize) |
|
void | usb_free_xfer_request (struct usb_xfer_request *req) |
|
usb_status_t | usb_submit_xfer_request (struct usb_xfer_request *req) |
|
void | usb_complete_xfer (struct usb_xfer_request *req) |
|
usb_status_t | usb_control_msg (struct usb_device *dev, const struct usb_endpoint_descriptor *endpoint_desc, uint8_t bRequest, uint8_t bmRequestType, uint16_t wValue, uint16_t wIndex, void *data, uint16_t wLength) |
|
usb_status_t | usb_get_descriptor (struct usb_device *dev, uint8_t bRequest, uint8_t bmRequestType, uint16_t wValue, uint16_t wIndex, void *buf, uint16_t buflen) |
|
struct usb_device * | usb_alloc_device (struct usb_device *parent) |
|
void | usb_free_device (struct usb_device *dev) |
|
usb_status_t | usb_attach_device (struct usb_device *dev) |
|
void | usb_lock_bus (void) |
|
void | usb_unlock_bus (void) |
|
usb_status_t | usb_register_device_driver (const struct usb_device_driver *drv) |
|
const char * | usb_status_string (usb_status_t status) |
|
const char * | usb_class_code_to_string (enum usb_class_code class_code) |
|
const char * | usb_speed_to_string (enum usb_speed speed) |
|
const char * | usb_transfer_type_to_string (enum usb_transfer_type type) |
|
const char * | usb_direction_to_string (enum usb_direction dir) |
|
usb_status_t | usb_get_string_descriptor (struct usb_device *dev, uint8_t index, uint16_t lang_id, struct usb_string_descriptor *buf, uint16_t buflen) |
|
usb_status_t | usb_get_ascii_string (struct usb_device *dev, uint32_t iString, char *strbuf, uint32_t strbufsize) |
|
const char * | usb_device_description (const struct usb_device *dev) |
|
USB device model and API for USB device drivers.
This is the USB Core Driver. It implements the USB system software that does not depend on the specific host controller hardware and is not specific to any single USB device or platform.
Features and limitations:
- This driver is written to be compatible with USB 2.0. USB 3.0 devices are untested.
- Not all USB transfer types and speeds are necessarily supported. This depends on the Host Controller Driver; see usb_submit_xfer_request().
- This driver does not attempt to do any intelligent power management, bandwidth allocation, or transfer scheduling. Devices are always set to their first listed configuration regardless of power requirements. Transfer requests are simply passed to the Host Controller Driver in the order submitted; thus, the Host Controller Driver is responsible for doing any more intelligent scheduling if desired.
- This driver is assumed to drive a single USB (bus). Multiple USBs are not supported.
- This driver does not support multiple configurations per USB device. If a device happens to have multiple configurations, the first one will be assigned.
- This driver is currently written to support binding drivers to USB devices rather than USB interfaces.
- By design, it is possible to implement a host controller driver for different host controller hardware without changing any of this code, as long as the host controller driver provides the functions declared in usb_hcdi.h.
- By design, this driver has a hard-coded dependency on the USB hub driver because USB is useless without hubs.
To initialize this core USB driver, usbinit() must be called by the system startup code. See that function for details.
The other functions exported by this core USB driver are mostly intended to be used by USB device drivers.
Debugging messages in this driver and in the rest of the USB code can be enabled by changing the definitions of the minimum, initial, and/or background log priorities in usb_util.h.
struct usb_device* usb_alloc_device |
( |
struct usb_device * |
parent | ) |
|
Allocate a USB device structure from the pool of available device structures.
- Parameters
-
parent | Pointer to the USB device structure for the parent hub, or NULL if the device being allocated is the root hub. |
- Returns
- Pointer to an initialized USB device structure, or
NULL
if no more USB device structures are available.
struct usb_xfer_request* usb_alloc_xfer_request |
( |
uint |
bufsize | ) |
|
Dynamically allocates a struct usb_xfer_request, including a data buffer.
- Parameters
-
bufsize | Length of the data buffer for sending and/or receiving. |
- Returns
- A pointer to the resulting struct usb_xfer_request, or NULL if out of memory.
usb_status_t usb_attach_device |
( |
struct usb_device * |
dev | ) |
|
Configure and initialize, or "enumerate", a newly allocated USB device. The physical device is initially assumed to be non-addressed and non-configured and therefore accessible by sending control messages to the default address of 0.
- Parameters
-
dev | New USB device to configure and initialize. |
- Returns
- ::USB_STATUS_SUCCESS if successful; another ::usb_status_t error code otherwise. Note that after a succesful return, the newly attached device may or may not have been bound to an actual device driver.
const char* usb_class_code_to_string |
( |
enum usb_class_code |
class_code | ) |
|
Translates a USB class code into a string describing it.
- Parameters
-
class_code | A USB class code constant. |
- Returns
- A constant string describing the USB class, or "Unknown" if the class code was not recognized.
void usb_complete_xfer |
( |
struct usb_xfer_request * |
req | ) |
|
Signal the device driver that a USB transfer has successfully completed or has encountered an error. Intended to be called by Host Controller Drivers only.
- Parameters
-
req | USB transfer to signal completion on. |
usb_status_t usb_control_msg |
( |
struct usb_device * |
dev, |
|
|
const struct usb_endpoint_descriptor * |
endpoint_desc, |
|
|
uint8_t |
bRequest, |
|
|
uint8_t |
bmRequestType, |
|
|
uint16_t |
wValue, |
|
|
uint16_t |
wIndex, |
|
|
void * |
data, |
|
|
uint16_t |
wLength |
|
) |
| |
Synchronously performs a control transfer to or from a USB device. Control messages are one of the four fundamental transfer types of USB and are documented in various places in the USB 2.0 specification.
This is a synchronous interface, so the thread will be blocked until the control transfer has completed, timed out, or encountered another error. Currently the request timeout is chosen by the Host Controller Driver and cannot be passed as a parameter.
- Parameters
-
dev | Pointer to the USB device to which to submit the control message. |
endpoint_desc | Pointer to the endpoint descriptor for the endpoint to which to submit the control transfer, or NULL to specify the default control endpoint (which has no endpoint descriptor). |
bRequest | Request to make. Standard device requests are documented in Section 9.4 of the USB 2.0 specification; in this code they are the enum ::usb_device_request values. Other values, such as class-specific requests, can also be used for this parameter. |
bmRequestType | Type of the request to make. Standard types are documented in Section 9.3.1 of the USB 2.0 specification; in this code they are the enum ::usb_bmRequestType_fields values. |
wValue | Request-specific data. |
wIndex | Request-specific data. |
data | Pointer to a buffer that, depending on the request, either contains the additional data to be sent as part of the message, or receives the additional data that will be received from the USB device. This parameter is ignored if wLength is 0. |
wLength | Length of the data buffer. This is interpreted as the exact number of additional bytes of data that must be transferred. This can be 0 if no additional data needs to be transferred to satisfy the request; for example, a SetAddress request passes information in wValue but uses no additional data buffer. |
- Returns
- Status of the transfer. The possible return values include:
- Return values
-
::USB_STATUS_SUCCESS | The transfer completed successfully with exactly the amount of data specified by wLength . |
::USB_STATUS_OUT_OF_MEMORY | Failed to allocate memory or create a semaphore. |
::USB_STATUS_INVALID_DATA | The transfer completed, but not with the exact amount of data specified. |
::USB_STATUS_UNSUPPORTED_REQUEST | The transfer was to the root hub, but the request was not implemented. |
::USB_STATUS_HARDWARE_ERROR | A hardware error occurred. |
::USB_STATUS_DEVICE_DETACHED | The USB device was detached. |
const char* usb_device_description |
( |
const struct usb_device * |
dev | ) |
|
Returns a fairly detailed, human-readable description of a USB device.
- Parameters
-
dev | USB device to get a description of. |
- Returns
- A string describing the device. The returned string is statically allocated and will be changed on the next call to this function.
const char* usb_direction_to_string |
( |
enum usb_direction |
dir | ) |
|
Translates a USB direction constant into a string describing it.
- Parameters
-
dir | A USB direction constant. |
- Returns
- "OUT", "IN", or "Unknown".
void usb_free_device |
( |
struct usb_device * |
dev | ) |
|
Detaches and frees a USB device. This unbinds the device driver, if one is bound, and returns the USB device structure to the pool of available device structures. Only the hub driver should need to call this function.
- Parameters
-
dev | Pointer to the USB device structure to detach. |
void usb_free_xfer_request |
( |
struct usb_xfer_request * |
req | ) |
|
Frees a struct usb_xfer_request allocated by usb_alloc_xfer_request().
- Parameters
-
req | A pointer to the struct usb_xfer_request to free. It must not be currently pending. NULL can be passed as a no-op. |
usb_status_t usb_get_ascii_string |
( |
struct usb_device * |
dev, |
|
|
uint32_t |
iString, |
|
|
char * |
strbuf, |
|
|
uint32_t |
strbufsize |
|
) |
| |
Retrieves the English version (if any) of a USB string descriptor and "translates" it from UTF-16LE to ASCII. The resulting string is null-terminated. UTF-16LE codepoints outside the ASCII range are simply replaced with question marks.
- Parameters
-
dev | Pointer to the USB device structure for the device from which to read the string descriptor. |
iString | Index of the string descriptor to read. |
strbuf | Buffer in which to place the ASCII string. |
strbufsize | Length of the strbuf buffer. |
- Returns
- Any value that can be returned by usb_get_string_descriptor(), plus ::USB_STATUS_INVALID_DATA if the list of available language IDs is empty.
usb_status_t usb_get_descriptor |
( |
struct usb_device * |
dev, |
|
|
uint8_t |
bRequest, |
|
|
uint8_t |
bmRequestType, |
|
|
uint16_t |
wValue, |
|
|
uint16_t |
wIndex, |
|
|
void * |
buf, |
|
|
uint16_t |
buflen |
|
) |
| |
Reads a descriptor from a USB device. This is a wrapper around usb_control_msg() that automatically handles reading the descriptor header and requesting the appropriate length.
- Parameters
-
- Returns
- Same possible return values as usb_control_msg(), or ::USB_STATUS_INVALID_DATA if the bLength field in the descriptor header is less than the size of the descriptor header itself.
usb_status_t usb_get_string_descriptor |
( |
struct usb_device * |
dev, |
|
|
uint8_t |
index, |
|
|
uint16_t |
lang_id, |
|
|
struct usb_string_descriptor * |
buf, |
|
|
uint16_t |
buflen |
|
) |
| |
Reads a USB string descriptor from a device.
- Parameters
-
dev | Pointer to the USB device structure for the device from which to read the string descriptor. |
index | Index of the string descriptor to read. For example, the iProduct member of the device descriptor specifies the index of the string descriptor that contains the product name. |
lang_id | Language ID of the language to request. Note: the available language IDs can be retrieved by requesting the string descriptor of index 0 with any language ID. |
buf | Buffer in which to place the string descriptor. |
buflen | Maximum length in bytes to read. |
- Returns
- See usb_get_descriptor().
void usb_init_xfer_request |
( |
struct usb_xfer_request * |
req | ) |
|
Performs one-time initialization on a USB transfer request allocated by the device driver in some way other than by usb_alloc_xfer_request().
- Parameters
-
req | Pointer to the USB transfer request to initialize. |
void usb_lock_bus |
( |
void |
| ) |
|
Prevent devices from being attached or detached to/from the USB. This does not prevent USB transfers from being issued on the bus.
usb_status_t usb_register_device_driver |
( |
const struct usb_device_driver * |
drv | ) |
|
Registers a USB device driver with the USB core. At any time after this is called, the USB core may execute the bind_device callback to try to bind the device driver to a USB device.
This currently can safely be called before usbinit().
- Parameters
-
drv | Pointer to the USB device driver structure to register. |
- Returns
- ::USB_STATUS_SUCCESS if the driver was successfully registered or was already registered; otherwise another ::usb_status_t error code.
const char* usb_speed_to_string |
( |
enum usb_speed |
speed | ) |
|
Translates a USB speed constant into a string describing it.
- Parameters
-
speed | A USB speed constant. |
- Returns
- "high", "full", "low", or "unknown".
const char* usb_status_string |
( |
usb_status_t |
status | ) |
|
Translates a ::usb_status_t into a string describing it.
- Parameters
-
status | A ::usb_status_t error code returned by one of the functions in Xinu's USB subsystem. |
- Returns
- A constant string describing the error, or "unknown error" if the error code is not recognized.
usb_status_t usb_submit_xfer_request |
( |
struct usb_xfer_request * |
req | ) |
|
Submit a USB transfer request to be completed.
This is intended to be an asynchronous interface where the transfer request is queued for later processing by the Host Controller. This function should immediately return and the transfer request should be asynchronously completed at some later time, making use of interrupts between the CPU and host controller to accomplish this efficiently. However, exactly how the transfer request is completed is ultimately up to the Host Controller Driver. Synchronous completion is possible, although not recommended.
When the transfer has been completed or has failed, the completion_cb_func function of the req
will be called. This callback function should process the completed or failed request and either free its memory or re-submit it to start another transfer.
Not all USB transfer types and speeds are necessarily supported. This depends on the Host Controller Driver, which is expected to make sure each request is supported when passed it and return ::USB_STATUS_INVALID_PARAMETER if not. Currently, the Host Controller Driver for the Synopsys DesignWare High-Speed USB 2.0 On-The-Go Controller (the one on the Raspberry Pi) is intended to support control, bulk, and interrupt transfers at low, full, and high speeds; however, not all combinations of transfers and speeds have actually been tested yet.
- Parameters
-
req | Pointer to the USB transfer request to submit. Its members documented as input must have been filled in. |
- Return values
-
::USB_STATUS_SUCCESS | The request was submitted successfully. |
::USB_STATUS_INVALID_PARAMETER | req was not filled in correctly. |
::USB_STATUS_DEVICE_DETACHED | The device has been detached. |
const char* usb_transfer_type_to_string |
( |
enum usb_transfer_type |
type | ) |
|
Translates a USB transfer type constant into a string describing it.
- Parameters
-
type | A USB transfer type constant. |
- Returns
- "Control", "Isochronous", "Bulk", "Interrupt", or "Unknown".
void usb_unlock_bus |
( |
void |
| ) |
|
Undo usb_lock_bus(), allowing devices to be attached or detached to/from the USB.