NAME
usbdi
—
USB device drivers interface
SYNOPSIS
#include
<dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include
<dev/usb/usbdi_util.h>
Functions offered by usbdi.h
usbd_status
usbd_open_pipe
(struct
usbd_interface *iface,
uint8_t address,
uint8_t flags,
struct usbd_pipe
**pipe);
usbd_status
usbd_close_pipe
(struct
usbd_pipe *pipe);
usbd_status
usbd_transfer
(struct
usbd_xfer *xfer);
struct usbd_xfer *
usbd_setup_xfer
(struct
usbd_xfer *xfer, void
*priv, void
*buffer, uint32_t
length, uint16_t
flags, uint32_t
timeout,
usbd_callback);
void
usbd_setup_default_xfer
(struct
usbd_xfer *xfer, struct
usbd_device *dev, void
*priv, uint32_t
timeout,
usb_device_request_t
*req, void
*buffer, uint32_t
length, uint16_t
flags,
usbd_callback);
void
usbd_setup_isoc_xfer
(struct
usbd_xfer *xfer, void
*priv, uint16_t
*frlengths, uint32_t
nframes, uint16_t
flags,
usbd_callback);
void
usbd_get_xfer_status
(struct
usbd_xfer *xfer, void
**priv, void
**buffer, uint32_t
*count, usbd_status
*status);
usb_endpoint_descriptor_t *
usbd_interface2endpoint_descriptor
(struct
usbd_interface *iface,
uint8_t address);
usbd_status
usbd_abort_pipe
(struct
usbd_pipe *pipe);
usbd_status
usbd_abort_default_pipe
(struct
usbd_device *dev);
usbd_status
usbd_clear_endpoint_stall
(struct
usbd_pipe *pipe);
usbd_status
usbd_clear_endpoint_stall_async
(struct
usbd_pipe *pipe);
void
usbd_clear_endpoint_toggle
(struct
usbd_pipe *pipe);
usbd_status
usbd_endpoint_count
(struct
usbd_interface *dev,
uint8_t *count);
usbd_status
usbd_interface_count
(struct
usbd_device *dev, uint8_t
*count);
usbd_status
usbd_interface2device_handle
(struct
usbd_interface *iface,
struct usbd_device
**dev);
usbd_status
usbd_device2interface_handle
(struct
usbd_device *dev, uint8_t
ifaceno, struct
usbd_interface **iface);
struct usbd_device *
usbd_pipe2device_handle
(struct
usbd_pipe *pipe);
int
usbd_create_xfer
(struct
usbd_pipe *pipe, size_t
len, unsigned int
flags, unsigned int
nframes, struct usbd_xfer
**xp);
void
usbd_destroy_xfer
(struct
usbd_xfer *xfer);
void *
usbd_get_buffer
(struct
usbd_xfer *xfer);
usbd_status
usbd_sync_transfer
(struct
usbd_xfer *req);
usbd_status
usbd_sync_transfer_sig
(struct
usbd_xfer *req);
usbd_status
usbd_open_pipe_intr
(struct
usbd_interface *iface,
uint8_t address,
uint8_t flags,
struct usbd_pipe **pipe,
void *priv,
void *buffer,
uint32_t length,
usbd_callback callback,
int interval);
usbd_status
usbd_do_request
(struct
usbd_device *dev,
usb_device_request_t
*req, void
*data);
usbd_status
usbd_do_request_flags
(struct
usbd_device *dev,
usb_device_request_t
*req, void *data,
uint16_t flags,
int *actlen,
uint32_t timo);
usb_interface_descriptor_t *
usbd_get_interface_descriptor
(struct
usbd_interface *iface);
usb_config_descriptor_t *
usbd_get_config_descriptor
(struct
usbd_device *dev);
usb_device_descriptor_t *
usbd_get_device_descriptor
(struct
usbd_device *dev);
usbd_status
usbd_set_interface
(struct
usbd_interface *iface,
int altidx);
int
usbd_get_no_alts
(usb_config_descriptor_t
*iface, int
ifaceno);
usbd_status
usbd_fill_deviceinfo
(struct
usbd_device *dev, struct
usb_device_info *di);
int
usbd_get_interface_altindex
(struct
usbd_interface *iface);
usb_endpoint_descriptor_t *
usbd_get_endpoint_descriptor
(struct
usbd_interface *dev,
uint8_t address);
usb_interface_descriptor_t *
usbd_find_idesc
(usb_config_descriptor_t
*cd, int iindex,
int ano);
usb_endpoint_descriptor_t *
usbd_find_edesc
(usb_config_descriptor_t
*cd, int ifaceidx,
int altidx,
int endptidx);
void
usbd_dopoll
(struct
usbd_interface *iface);
void
usbd_set_polling
(struct
usbd_device *iface, int
val);
const char *
usbd_errstr
(usbd_status
err);
void
usbd_add_dev_event
(int
type, struct usbd_device
*iface);
void
usbd_add_drv_event
(int
type, struct usbd_device
*iface, device_t
dv);
char *
usbd_devinfo_alloc
(struct
usbd_device *iface, int
showclass);
void
usbd_devinfo_free
(char
*str);
const struct usbd_quirks *
usbd_get_quirks
(struct
usbd_device *iface);
usbd_status
usbd_reload_device_desc
(struct
usbd_device *iface);
int
usbd_ratecheck
(struct
timeval *tv);
usbd_status
usbd_get_string
(struct
usbd_device *iface, int
si, char *buf);
usbd_status
usbd_get_string0
(struct
usbd_device *iface, int
si, char *buf,
int unicode);
void
usb_desc_iter_init
(struct
usbd_device *iface,
usbd_desc_iter_t
*iter);
const usb_descriptor_t *
usb_desc_iter_next
(usbd_desc_iter_t
*iter);
void
usb_add_task
(struct
usbd_device *iface,
struct usb_task *task,
int queue);
void
usb_rem_task
(struct
usbd_device *iface,
struct usb_task
*task);
void
usb_init_task
(struct
usb_task *task, void
(*func)(void *), void
*arg, uint8_t,
flags);
const struct usb_devno *
usb_lookup
(const
struct usb_devno *tbl,
uint16_t vendor,
uint16_t product);
Obsolete functions
The following functions have been obsoleted from
usbdi.h
.
void *
usbd_alloc_buffer
(struct
usbd_xfer *xfer, uint32_t
size);
void
usbd_free_buffer
(struct
usbd_xfer *xfer);
Utilities from usbdi_util.h
Based on the routines in usbdi.h
a number
of utility functions have been defined that are accessible through
usbdi_util.h
.
usbd_status
usbd_get_desc
(struct
usbd_device *dev, int
type, int index,
int len,
void *desc);
usbd_status
usbd_get_config_desc
(struct
usbd_device *dev, int
confidx,
usb_config_descriptor_t
*d);
usbd_status
usbd_get_config_desc_full
(struct
usbd_device *, int
dev, void *d,
int size);
usbd_status
usbd_get_device_desc
(struct
usbd_device *dev,
usb_device_descriptor_t
*d);
usbd_status
usbd_set_address
(struct
usbd_device *dev, int
addr);
usbd_status
usbd_get_port_status
(struct
usbd_device *dev, int
port, usb_port_status_t
*ps);
usbd_status
usbd_set_hub_feature
(struct
usbd_device *dev, int
sel);
usbd_status
usbd_clear_hub_feature
(struct
usbd_device *dev, int
sel);
usbd_status
usbd_set_port_feature
(struct
usbd_device *dev, int
port, int sel);
usbd_status
usbd_clear_port_feature
(struct
usbd_device *dev, int
port, int sel);
usbd_status
usbd_get_device_status
(struct
usbd_device *dev,
usb_status_t *st);
usbd_status
usbd_get_hub_status
(struct
usbd_device *dev,
usb_hub_status_t
*st);
usbd_status
usbd_set_protocol
(struct
usbd_interface *dev, int
report);
usbd_status
usbd_get_report_descriptor
(struct
usbd_device *dev, int
ifcno, int repid,
int size,
void *d);
struct usb_hid_descriptor *
usbd_get_hid_descriptor
(struct
usbd_interface *ifc);
usbd_status
usbd_set_report
(struct
usbd_interface *iface,
int type,
int id,
void *data,
int len);
usbd_status
usbd_set_report_async
(struct
usbd_interface *iface,
int type,
int id,
void *data,
int len);
usbd_status
usbd_get_report
(struct
usbd_interface *iface,
int type,
int id,
void *data,
int len);
usbd_status
usbd_set_idle
(struct
usbd_interface *iface,
int duration,
int id);
usbd_status
usbd_alloc_report_desc
(struct
usbd_interface *ifc, void
**descp, int
*sizep, int
mem);
usbd_status
usbd_get_string_desc
(struct
usbd_device *dev, int
sindex, int langid,
usb_string_descriptor_t
*sdesc);
void
usbd_delay_ms
(struct
usbd_device *dev, u_int
ms);
usbd_status
usbd_set_config_no
(struct
usbd_device *dev, int
no, int msg);
usbd_status
usbd_set_config_index
(struct
usbd_device *dev, int
index, int
msg);
usbd_status
usbd_bulk_transfer
(struct
usbd_xfer *xfer, struct
usbd_pipe *pipe, uint16_t
flags, uint32_t
timeout, void *buf,
uint32_t *size);
usbd_status
usbd_intr_transfer
(struct
usbd_xfer *xfer, struct
usbd_pipe *pipe, uint16_t
flags, uint32_t
timeout, void *buf,
uint32_t *size);
void
usb_detach_waitold
(device_t
dv);
void
usb_detach_wakeupold
(device_t
dv);
void
usb_detach_wait
(device_t
dv, kcondvar_t *cv,
kmutex_t *lk);
void
usb_detach_broadcast
(device_t
dv, kcondvar_t
*cv);
DESCRIPTION
Device driver access to the USB bus centers around transfers. A transfer describes a communication with a USB device. A transfer is an abstract concept that can result in several physical packets being transferred to or from a device. A transfer is described by the struct usbd_xfer * cookie. A pipe is a logical connection to a USB device. It is described by the struct usbd_pipe * cookie. See the TRANSFERS and PIPES sections for more details.
There are a number of functions to obtain a handle, descriptor or resource count:
usbd_device2interface_handle
(dev, ifaceno, iface)- Fills in iface with the struct usbd_interface * for the USB device dev on interface number ifaceno.
usbd_interface2device_handle
(iface, dev)- Fills in dev with the struct usbd_device * pointer for interface iface.
usbd_pipe2device_handle
(pipe)- Returns the struct usbd_device * associated with pipe.
usbd_interface2endpoint_descriptor
(iface, address)- Returns the usb_endpoint_descriptor_t * for the particular interface iface at address address.
usbd_endpoint_count
(dev, count)usbd_interface_count
(dev, count)- Fills in count with the number of endpoint or interfaces the USB device dev has.
Error handling and other return values are described in usbd_status(9).
Additional comments on particular functions:
usbd_errstr
(err)- Returns the string associated with err.
usbd_add_dev_event
(type, iface)- The type must be one of
USB_EVENT_CTRLR_ATTACH
,USB_EVENT_CTRLR_DETACH
,USB_EVENT_DEVICE_ATTACH
andUSB_EVENT_DEVICE_DETACH
. usbd_add_drv_event
(type, iface, dv)- The type must be one of
USB_EVENT_DRIVER_ATTACH
andUSB_EVENT_DRIVER_DETACH
. The dv corresponds with the device_t associated with the device attached or detached. usb_lookup
(tbl, vendor, product)- Lookup a USB device. The returned struct usb_devno
pointer has these members:
- uint16_t ud_vendor;
- uint16_t ud_product;
USB_PRODUCT_ANY
macro can be used to match any USB product by a particular vendor.
PIPES
Pipes are created and destroyed by using the
usbd_open_pipe
(),
usbd_open_pipe_intr
() and
usbd_close_pipe
() functions. The open functions take
the interface handle iface, the
address of this pipe and flags
for this pipe which currently may be 0, or a combination of
USBD_EXCLUSIVE_USE
, to enable exclusive access to
this interface and address, and USBD_MPSAFE
, to
allow running transfer callbacks on this pipe without first acquiring
kernel_lock
. The
usbd_open_pipe_intr
() takes additional arguments
priv to set the default private handle.
buffer and len to describe the
buffer to be used, callback for the function to call
at interrupt time, and finally the interval for
interrupts to be delivered in milliseconds. The
interval may be set to
USBD_DEFAULT_INTERVAL
use the default interval,
specified by the ep. description. It is common to have more than one pipe
per device.
TRANSFERS
Transfers are created and destroyed with
usbd_create_xfer
()
and
usbd_destroy_xfer
(),
respectively, and are associated with a pipe at their creation time. The
create function takes the pipe handle pipe, the length
of the largest transfer possible len, possible
transfer flags flags, the number of isochronous frames
(or 0) in nframes.
The data describing the transfer is
filled by either
usbd_setup_default_xfer
()
for control pipe transfers, by
usbd_setup_xfer
()
for bulk and interrupt transfers, and by
usbd_setup_isoc_xfer
()
for isochronous transfers. Private data may be passed between setup and
completion or status calls using the void *priv
argument.
Arguments to the setup functions include the newly allocated xfer, the private data priv, the timeout in milliseconds, for control, bulk and interrupt transfers buffer the data to transfer and its length and for isochronous transfers the frame length frlengths and number of frames nframes, and for default transfers a USB request structure req must be presented. See the INITIALISING USB REQUESTS section for more details on USB requests.
The transfer specific flags that can be set are:
USBD_SYNCHRONOUS
- Wait for completion
USBD_SYNCHRONOUS_SIG
- When waiting for completion, allow signals to trigger wake up.
USBD_SHORT_XFER_OK
- Short reads are not an error
USBD_FORCE_SHORT_XFER
- Force last short packet on write
The
usbd_get_buffer
()
function returns the current kernel address for the buffer suitable for
transfer in xfer.
The
usbd_open_pipe
(),
usbd_open_pipe_intr
(),
usbd_close_pipe
(),
usbd_alloc_xfer
(),
and
usbd_free_xfer
()
can all sleep and should not be called from interrupt context as a
result.
Upon completion the callback function is called, which takes the completed xfer, the private data priv originally assocated with this transfer, and status the status of this transfer.
Transfers are initiated by calling
usbd_transfer
(),
and their results made be later obtained by calling
usbd_get_xfer_status, which fills in the private data
priv, original buffer location
buffer, the length length, and
the status of this request.
The
usbd_bulk_transfer
()
and
usbd_intr_transfer
()
functions are used to transfer data in either an interrupt or bulk fashion,
and are front-ends to the usbd_setup_xfer
(),
usbd_transfer
() and
usbd_get_xfer_status
(),
as well as associated error handling. The
usbd_sync_transfer
()
is identical to usbd_transfer
() with the
USBD_SYNCHRONOUS
flag set. The
usbd_sync_transfer_sig
()
is identical to usbd_transfer
() with the
USBD_SYNCHRONOUS
and
USBD_SYNCHRONOUS_SIG
flags set.
Transfers are aborted via this pipe with
usbd_abort_pipe
()
and
usbd_abort_default_pipe
().
The
usbd_clear_endpoint_stall
()
and
usbd_clear_endpoint_stall_async
()
functions are used to clear endpoint halt in either a synchronous or
asynchronous fashion. To clear the toggle state of an endpoint the
usbd_clear_endpoint_toggle
()
function should be used.
A request is described by a
usb_device_request_t which must be initialised as
necessary before calling either
usbd_do_request
()
or
usbd_do_request_flags
()
to submit the request. For both these functions dev is
the handle of the USB device the request is for, req
is the USB request, as described in the
INITIALISING USB
REQUESTS section, and then data is a buffer
containing the data for the request. For the
usbd_do_request_flags
() function there are
additional flags passed to the
usbd_setup function, actlen a
pointer to fill in with the actual length of this request, and
timo, the number of milliseconds to wait before timing
out this request.
INITIALISING USB REQUESTS
There are 5 members of a usb_device_request_t that must be initialised:
- uByte bmRequestType;
- uByte bRequest;
- uWord wValue;
- uWord wIndex;
- uWord wLength;
The first two are normal byte values that may be simply
assigned, but the last three must be initialised with the
USETW
()
macro.
The bmRequestType holds the request type of this USB request, which describes the intended recipient of the request.
This may be one of:
with one of:
and with one of:
These are also in combinations as:
UT_READ_DEVICE
UT_READ_INTERFACE
UT_READ_ENDPOINT
UT_WRITE_DEVICE
UT_WRITE_INTERFACE
UT_WRITE_ENDPOINT
UT_READ_CLASS_DEVICE
UT_READ_CLASS_INTERFACE
UT_READ_CLASS_OTHER
UT_READ_CLASS_ENDPOINT
UT_WRITE_CLASS_DEVICE
UT_WRITE_CLASS_INTERFACE
UT_WRITE_CLASS_OTHER
UT_WRITE_CLASS_ENDPOINT
UT_READ_VENDOR_DEVICE
UT_READ_VENDOR_INTERFACE
UT_READ_VENDOR_OTHER
UT_READ_VENDOR_ENDPOINT
UT_WRITE_VENDOR_DEVICE
UT_WRITE_VENDOR_INTERFACE
UT_WRITE_VENDOR_OTHER
UT_WRITE_VENDOR_ENDPOINT
The bRequest describes which request is being made. The available values are:
The wValue,
wIndex and wLength are
device-specific values and must be initialised with the
USETW
()
macro.
USB REQUEST TYPES AND STRUCTURES
The UR_GET_STATUS
request operates on a
usb_status_t structure, which has this member:
- uWord wStatus;
For device status requests the wStatus member may have either of these bit flags set:
For endpoint status requests the wStatus member may have this bit flag set:
The UR_CLEAR_FEATURE
and
UR_SET_FEATURE
requests clear or set special
features on USB devices. The values for wValue,
wIndex and wLength depend upon
the device and device type.
The UR_SET_ADDRESS
request sets the
virtual USB address of a port using the wValue.
The UR_GET_DESCRIPTOR
and
UR_SET_DESCRIPTOR
requests operate on a
usb_descriptor_t structure, which has these
members:
- uByte bLength;
- uByte bDescriptorType;
The bDescriptorType member may be one of the following values:
The
usbd_set_interface
()
function can be used to change the index used for transfers on this
interface as obtained via
usbd_device2interface_handle
().
USB DEVICE DETACHMENT
There are two functions available to ease the detach of active
devices. Typically a reference count is maintained on syscall activity. When
a USB device is to be detached, the reference count should be decremented
and if it is greater or equal to zero,
usb_detach_wait
() should be called on the
dv associated with this USB device and, typically, a
device-specific condition variable cv. and mutex
lk protecting this reference count state. At the end
of each syscall function, if the reference count is decremented to less than
zero, then
usb_detach_broadcast
()
must be called on the dv and cv
that is being waited on with usb_detach_wait
().
The are another pair of functions with
similar functionality that do not use a condition variable or mutex and
should be avoided in new code. The
usb_detach_waitold
()
function works like
usb_detach_wait
(),
and the
usb_detach_wakeupold
()
function works like
usb_detach_broadcast
().
USB TASK MANAGEMENT
The USB stack provides a task management framework to execute tasks in a thread context at the soonest opportunity. Typically this is used by network drivers to handle periodic updates or status change requests, or other operations that need to run in a normal context.
The
usb_init_task
()
function takes a pointer to a struct usb_task that
will be initalised, a function to call for this task
func, the argument to pass to
func, arg, and the task flags
flags. If the flags argument is
USB_TASKQ_MPSAFE
, the func
function will be called without first acquiring
kernel_lock
.
To invoke the task callback the
usb_add_task
()
function should be called with the iface associated
with this device, the task structure task, and the
queue to run against, either
USB_TASKQ_HC
for operations initiated by host
controllers or USB_TASKQ_DRIVER
for operations
initiated by USB drivers.
To deschedule a potentially running task the
usb_rem_task
()
function should be called.
The driver using these facilities is expected
to provide the necessary serialisation between
usb_init_task
(),
usb_add_task
() and
usb_rem_task
() for each specific
struct usb_task.
SEE ALSO
HISTORY
This usbdi
interface first appeared in
NetBSD 1.4. The interface is based on an early
definition from the OpenUSBDI group within the USB organisation. Right after
this definition the OpenUSBDI development got closed for open source
developers, so this interface has not followed the further changes. The
OpenUSBDI specification is now available again, but looks different.
BUGS
This manual is under development, so its biggest shortcoming is incompleteness.