freebsd-dev/share/man/man9/usbdi.9

1254 lines
34 KiB
Groff
Raw Normal View History

.\"
.\" Copyright (c) 2005 Ian Dowse <iedowse@FreeBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.Dd December 30, 2005
.Os
.Dt USBDI 9
.Sh NAME
.Nm usb_detach_wait ,
.Nm usb_detach_wakeup ,
.Nm usb_find_desc ,
.Nm usbd_abort_default_pipe ,
.Nm usbd_abort_pipe ,
.Nm usbd_alloc_buffer ,
.Nm usbd_alloc_xfer ,
.Nm usbd_bulk_transfer ,
.Nm usbd_clear_endpoint_stall ,
.Nm usbd_clear_endpoint_stall_async ,
.Nm usbd_clear_endpoint_toggle ,
.Nm usbd_close_pipe ,
.Nm usbd_device2interface_handle ,
.Nm usbd_devinfo ,
.Nm usbd_do_request ,
.Nm usbd_do_request_async ,
.Nm usbd_do_request_flags ,
.Nm usbd_do_request_flags_pipe ,
.Nm usbd_dopoll ,
.Nm usbd_endpoint_count ,
.Nm usbd_errstr ,
.Nm usbd_fill_deviceinfo ,
.Nm usbd_find_edesc ,
.Nm usbd_find_idesc ,
.Nm usbd_free_buffer ,
.Nm usbd_free_xfer ,
.Nm usbd_get_buffer ,
.Nm usbd_get_config ,
.Nm usbd_get_config_desc ,
.Nm usbd_get_config_desc_full ,
.Nm usbd_get_config_descriptor ,
.Nm usbd_get_device_descriptor ,
.Nm usbd_get_endpoint_descriptor ,
.Nm usbd_get_interface_altindex ,
.Nm usbd_get_interface_descriptor ,
.Nm usbd_get_no_alts ,
.Nm usbd_get_quirks ,
.Nm usbd_get_speed ,
.Nm usbd_get_string ,
.Nm usbd_get_string_desc ,
.Nm usbd_get_xfer_status ,
.Nm usbd_interface2device_handle ,
.Nm usbd_interface2endpoint_descriptor ,
.Nm usbd_interface_count ,
.Nm usbd_intr_transfer ,
.Nm usbd_open_pipe ,
.Nm usbd_open_pipe_intr ,
.Nm usbd_pipe2device_handle ,
.Nm usbd_ratecheck ,
.Nm usbd_set_config_index ,
.Nm usbd_set_config_no ,
.Nm usbd_set_interface ,
.Nm usbd_set_polling ,
.Nm usbd_setup_default_xfer ,
.Nm usbd_setup_isoc_xfer ,
.Nm usbd_setup_xfer ,
.Nm usbd_sync_transfer ,
.Nm usbd_transfer
.Nd Universal Serial Bus driver programming interface
.Sh SYNOPSIS
.In dev/usb/usb.h
.In dev/usb/usbdi.h
.In dev/usb/usbdi_util.h
.Pp
.Ft void
.Fn usb_detach_wait "device_ptr_t dv"
.Ft void
.Fn usb_detach_wakeup "device_ptr_t dv"
.Ft "const usb_descriptor_t *"
.Fn usb_find_desc "usbd_device_handle dev" "int type" "int subtype"
.Ft usbd_status
.Fn usbd_abort_default_pipe "usbd_device_handle dev"
.Ft usbd_status
.Fn usbd_abort_pipe "usbd_pipe_handle pipe"
.Ft "void *"
.Fn usbd_alloc_buffer "usbd_xfer_handle xfer" "u_int32_t size"
.Ft usbd_xfer_handle
.Fn usbd_alloc_xfer "usbd_device_handle dev"
.Ft usbd_status
.Fo usbd_bulk_transfer
.Fa "usbd_xfer_handle xfer"
.Fa "usbd_pipe_handle pipe"
.Fa "u_int16_t flags"
.Fa "u_int32_t timeout"
.Fa "void *buf"
.Fa "u_int32_t *size"
.Fa "char *lbl"
.Fc
.Ft usbd_status
.Fn usbd_clear_endpoint_stall "usbd_pipe_handle pipe"
.Ft usbd_status
.Fn usbd_clear_endpoint_stall_async "usbd_pipe_handle"
.Ft void
.Fn usbd_clear_endpoint_toggle "usbd_pipe_handle pipe"
.Ft usbd_status
.Fn usbd_close_pipe "usbd_pipe_handle pipe"
.Ft usbd_status
.Fo usbd_device2interface_handle
.Fa "usbd_device_handle dev"
.Fa "u_int8_t ifaceno"
.Fa "usbd_interface_handle *iface"
.Fc
.Ft void
.Fn usbd_devinfo "usbd_device_handle dev" "int showclass" "char *cp"
.Ft usbd_status
.Fo usbd_do_request
.Fa "usbd_device_handle dev"
.Fa "usb_device_request_t *req"
.Fa "void *data"
.Fc
.Ft usbd_status
.Fo usbd_do_request_async
.Fa "usbd_device_handle dev"
.Fa "usb_device_request_t *req"
.Fa "void *data"
.Fc
.Ft usbd_status
.Fo usbd_do_request_flags
.Fa "usbd_device_handle dev"
.Fa "usb_device_request_t *req"
.Fa "void *data"
.Fa "u_int16_t flags"
.Fa "int *actlen"
.Fa "u_int32_t timo"
.Fc
.Ft usbd_status
.Fo usbd_do_request_flags_pipe
.Fa "usbd_device_handle dev"
.Fa "usbd_pipe_handle pipe"
.Fa "usb_device_request_t *req"
.Fa "void *data"
.Fa "u_int16_t flags"
.Fa "int *actlen"
.Fa "u_int32_t timeout"
.Fc
.Ft void
.Fn usbd_dopoll "usbd_interface_handle iface"
.Ft usbd_status
.Fn usbd_endpoint_count "usbd_interface_handle iface" "u_int8_t *count"
.Ft "const char *"
.Fn usbd_errstr "usbd_status err"
.Ft void
.Fo usbd_fill_deviceinfo
.Fa "usbd_device_handle dev"
.Fa "struct usb_device_info *di"
.Fa "int usedev"
.Fc
.Ft "usb_endpoint_descriptor_t *"
.Fo usbd_find_edesc
.Fa "usb_config_descriptor_t *cd"
.Fa "int ifaceidx"
.Fa "int altidx"
.Fa "int endptidx"
.Fc
.Ft "usb_interface_descriptor_t *"
.Fn usbd_find_idesc "usb_config_descriptor_t *cd" "int ifaceidx" "int altidx"
.Ft void
.Fn usbd_free_buffer "usbd_xfer_handle xfer"
.Ft usbd_status
.Fn usbd_free_xfer "usbd_xfer_handle xfer"
.Ft "void *"
.Fn usbd_get_buffer "usbd_xfer_handle xfer"
.Ft usbd_status
.Fn usbd_get_config "usbd_device_handle dev" "u_int8_t *conf"
.Ft usbd_status
.Fo usbd_get_config_desc
.Fa "usbd_device_handle dev"
.Fa "int confidx"
.Fa "usb_config_descriptor_t *d"
.Fc
.Ft usbd_status
.Fo usbd_get_config_desc_full
.Fa "usbd_device_handle dev"
.Fa "int conf"
.Fa "void *d"
.Fa "int size"
.Fc
.Ft "usb_config_descriptor_t *"
.Fn usbd_get_config_descriptor "usbd_device_handle dev"
.Ft "usb_device_descriptor_t *"
.Fn usbd_get_device_descriptor "usbd_device_handle dev"
.Ft "usb_endpoint_descriptor_t *"
.Fo usbd_get_endpoint_descriptor
.Fa "usbd_interface_handle iface"
.Fa "u_int8_t address"
.Fc
.Ft int
.Fn usbd_get_interface_altindex "usbd_interface_handle iface"
.Ft "usb_interface_descriptor_t *"
.Fn usbd_get_interface_descriptor "usbd_interface_handle iface"
.Ft int
.Fn usbd_get_no_alts "usb_config_descriptor_t *cdesc" "int ifaceno"
.Ft "const struct usbd_quirks *"
.Fn usbd_get_quirks "usbd_device_handle dev"
.Ft int
.Fn usbd_get_speed "usbd_device_handle dev"
.Ft usbd_status
.Fn usbd_get_string "usbd_device_handle dev" "int si" "char *buf"
.Ft usbd_status
.Fo usbd_get_string_desc
.Fa "usbd_device_handle dev"
.Fa "int sindex"
.Fa "int langid"
.Fa "usb_string_descriptor_t *sdesc"
.Fa "int *sizep"
.Fc
.Ft void
.Fo usbd_get_xfer_status
.Fa "usbd_xfer_handle xfer"
.Fa "usbd_private_handle *priv"
.Fa "void **buffer"
.Fa "u_int32_t *count"
.Fa "usbd_status *status"
.Fc
.Ft void
.Fo usbd_interface2device_handle
.Fa "usbd_interface_handle iface"
.Fa "usbd_device_handle *dev"
.Fc
.Ft "usb_endpoint_descriptor_t *"
.Fo usbd_interface2endpoint_descriptor
.Fa "usbd_interface_handle iface"
.Fa "u_int8_t index"
.Fc
.Ft usbd_status
.Fn usbd_interface_count "usbd_device_handle dev" "u_int8_t *count"
.Ft usbd_status
.Fo usbd_intr_transfer
.Fa "usbd_xfer_handle xfer"
.Fa "usbd_pipe_handle pipe"
.Fa "u_int16_t flags"
.Fa "u_int32_t timeout"
.Fa "void *buf"
.Fa "u_int32_t *size"
.Fa "char *lbl"
.Fc
.Ft usbd_status
.Fo usbd_open_pipe
.Fa "usbd_interface_handle iface"
.Fa "u_int8_t address"
.Fa "u_int8_t flags"
.Fa "usbd_pipe_handle *pipe"
.Fc
.Ft usbd_status
.Fo usbd_open_pipe_intr
.Fa "usbd_interface_handle iface"
.Fa "u_int8_t address"
.Fa "u_int8_t flags"
.Fa "usbd_pipe_handle *pipe"
.Fa "usbd_private_handle priv"
.Fa "void *buffer"
.Fa "u_int32_t len"
.Fa "usbd_callback cb"
.Fa "int ival"
.Fc
.Ft usbd_device_handle
.Fn usbd_pipe2device_handle "usbd_pipe_handle pipe"
.Ft int
.Fn usbd_ratecheck "struct timeval *last"
.Ft usbd_status
.Fn usbd_set_config_index "usbd_device_handle dev" "int index" "int msg"
.Ft usbd_status
.Fn usbd_set_config_no "usbd_device_handle dev" "int no" "int msg"
.Ft usbd_status
.Fn usbd_set_interface "usbd_interface_handle iface" "int altidx"
.Ft void
.Fn usbd_set_polling "usbd_device_handle dev" "int on"
.Ft void
.Fo usbd_setup_default_xfer
.Fa "usbd_xfer_handle xfer"
.Fa "usbd_device_handle dev"
.Fa "usbd_private_handle priv"
.Fa "u_int32_t timeout"
.Fa "usb_device_request_t *req"
.Fa "void *buffer"
.Fa "u_int32_t length"
.Fa "u_int16_t flags"
.Fa "usbd_callback callback"
.Fc
.Ft void
.Fo usbd_setup_isoc_xfer
.Fa "usbd_xfer_handle xfer"
.Fa "usbd_pipe_handle pipe"
.Fa "usbd_private_handle priv"
.Fa "u_int16_t *frlengths"
.Fa "u_int32_t nframes"
.Fa "u_int16_t flags"
.Fa "usbd_callback callback"
.Fc
.Ft void
.Fo usbd_setup_xfer
.Fa "usbd_xfer_handle xfer"
.Fa "usbd_pipe_handle pipe"
.Fa "usbd_private_handle priv"
.Fa "void *buffer"
.Fa "u_int32_t length"
.Fa "u_int16_t flags"
.Fa "u_int32_t timeout"
.Fa "usbd_callback callback"
.Fc
.Ft usbd_status
.Fn usbd_sync_transfer "usbd_xfer_handle xfer"
.Ft usbd_status
.Fn usbd_transfer "usbd_xfer_handle xfer"
.Sh DESCRIPTION
The Universal Serial Bus (USB) driver programming interface provides
USB peripheral drivers with a host controller independent API for
controlling and communicating with USB peripherals.
.Pp
Typically, drivers will first use some combination of the functions
.Fn usbd_set_config_no ,
.Fn usbd_get_config_descriptor ,
.Fn usbd_set_interface ,
.Fn usbd_get_interface_descriptor ,
.Fn usbd_device2interface_handle ,
.Fn usbd_endpoint_count
and
.Fn usbd_interface2endpoint_descriptor
to query the device's properties and prepare it for use.
Drivers can then perform requests on the USB control pipe using
.Fn usbd_do_request ,
they can open pipes using the functions
.Fn usbd_open_pipe
and
.Fn usbd_open_pipe_intr ,
and perform transfers over these pipes using
.Fn usbd_alloc_xfer ,
.Fn usbd_setup_xfer
and
.Fn usbd_transfer .
Finally, the functions
.Fn usbd_abort_pipe ,
.Fn usbd_close_pipe
and
.Fn usbd_free_xfer
are used to cancel outstanding transfers, close open pipes and deallocate
transfer structures.
.Pp
The
.Fn usbd_get_device_descriptor
function returns a pointer to the USB device descriptor for
.Fa dev .
See
.Sx "USB Descriptors"
below for information about the USB device descriptor.
.Pp
The
.Fn usbd_get_config_desc
function retrieves the specified configuration descriptor from the device.
The
.Fa confidx
parameter specifies the configuration descriptor index, which must be less
than the
.Fa bNumConfigurations
value in the device descriptor.
The function
.Fn usbd_get_config_desc_full
retrieves a full configuration descriptor, which has all related interface
and endpoint descriptors appended to a normal configuration descriptor.
The parameter
.Fa d
should point to memory that is at least
.Fa size
bytes in length, and this should be at least as long as the
.Fa wTotalLength
value from the configuration descriptor.
See
.Sx "USB Descriptors"
below for information about the USB configuration descriptor.
.Pp
The
.Fn usbd_get_config
function retrieves the current configuration number from the device, i.e.\&
the
.Fa bConfigurationValue
value from the configuration that is active.
If the device is unconfigured then
.Dv USB_UNCONFIG_NO
is returned.
The current configuration can be changed by calling either
.Fn usbd_set_config_index
or
.Fn usbd_set_config_no .
The difference between these functions is that
.Fn usbd_set_config_index
accepts a configuration index number that is less than the
.Fa bNumConfigurations
value from the device descriptor, whereas
.Fn usbd_set_config_no
requires the
.Fa bConfigurationValue
value of the desired configuration to be provided instead.
To unconfigure the device, supply a configuration index of
.Dv USB_UNCONFIG_INDEX
to
.Fn usbd_set_config_index ,
or else specify a configuration number of
.Dv USB_UNCONFIG_NO
to
.Fn usbd_set_config_no .
.Pp
The
.Fn usbd_get_config_descriptor
function returns a pointer to an in-memory copy of the full configuration
descriptor of the configuration that is currently active.
The returned pointer remains valid until the device configuration
is changed using
.Fn usbd_set_config_index
or
.Fn usbd_set_config_no .
If the device is unconfigured then
.Dv NULL
is returned instead.
.Pp
The function
.Fn usbd_interface_count
returns the number of interfaces available in the current device
configuration.
The
.Fn usbd_get_no_alts
function determines the number of alternate interfaces in a full
configuration descriptor by counting the interface descriptors with
.Fa bInterfaceNumber
equal to
.Fa ifaceno
(the count includes alternate index zero).
The
.Fn usbd_find_idesc
function locates an interface descriptor within a full configuration
descriptor.
The
.Fa ifaceidx
parameter specifies the interface index number, which should be less than
the number of interfaces in the configuration descriptor (i.e.\& the value
returned by
.Fn usbd_interface_count
or the
.Fa bNumInterface
field from the configuration descriptor).
An alternate interface can be specified using a non-zero
.Fa altidx ,
which should be less than the value returned by
.Fn usbd_get_no_alts .
The return value is a pointer to the requested interface descriptor
within the full configuration descriptor, or
.Dv NULL
if the specified interface descriptor does not exist.
Note that the
.Fa altidx
parameter specifies the alternate setting by index number starting
at zero; it is not the alternate setting number defined in the
interface descriptor.
.Pp
The function
.Fn usbd_find_edesc
locates an endpoint descriptor within a full configuration descriptor.
The
.Fa ifaceidx
and
.Fa altidx
parameters are the same as described for
.Fn usbd_find_idesc ,
and the
.Fa endptidx
parameter is an endpoint index number that should be less than the
.Fa bNumEndpoints
field in the interface descriptor.
The return value is a pointer to the requested endpoint descriptor
within the full configuration descriptor, or
.Dv NULL
if the specified endpoint descriptor does not exist.
Note that the
.Fa altidx
and
.Fa endptidx
parameters are index numbers starting at zero; they are not the
alternate setting and endpoint address defined in the descriptors.
.Pp
The
.Fn usbd_get_speed
function returns the device speed.
This can be
.Dv USB_SPEED_LOW ,
.Dv USB_SPEED_FULL
or
.Dv USB_SPEED_HIGH .
.Pp
USB devices optionally support string descriptors, which can be
retrieved using the
.Fn usbd_get_string
or
.Fn usbd_get_string_desc
functions.
Device, configuration and interface descriptors reference strings by
an index number that can be supplied to these functions.
The
.Fn usbd_get_string
function should be used unless a non-default language is required.
It requires that
.Fa buf
points to a buffer of at least
.Dv USB_MAX_STRING_LEN
bytes in size.
The
.Fa si
parameter specified which string to retrieve.
.Pp
The
.Fn usb_find_desc
function searches through the in-memory full configuration descriptor
for the active configuration and finds the first descriptor that has a
.Fa bDescriptorType
equal to
.Fa type ,
and if
.Fa subtype
is not equal to
.Dv USBD_SUBTYPE_ANY ,
the descriptor must also have a
.Fa bDescriptorSubtype
equal to
.Fa subtype .
If found, then a pointer to the descriptor is returned.
Otherwise,
.Fn usb_find_desc
returns
.Dv NULL .
The returned pointer is valid until the device configuration is changed using
.Fn usbd_set_config_index
or
.Fn usbd_set_config_no .
.Pp
The USB driver interface uses opaque interface handles to refer to
configuration interfaces.
These handles remain valid until the device configuration is changed using
.Fn usbd_set_config_index
or
.Fn usbd_set_config_no .
The
.Fn usbd_device2interface_handle
function retrieves an interface handle.
The
.Fa ifaceno
parameter is an interface index number starting at zero.
If the device is configured and the specified interface exists, then
.Dv USBD_NORMAL_COMPLETION
is returned and the interface handle is stored in
.Fa *iface .
Otherwise an error code is returned and
.Fa *iface
is not changed.
The
.Fn usbd_interface2device_handle
function retrieves the device handle from an interface handle.
This is just for convenience to save passing around the device
handle as well as the interface handle.
The
.Fn usbd_set_interface
function changes the alternate setting number for an interface to
the alternate setting identified by the zero-based index number
.Fa altidx .
This operation invalidates any existing endpoints on this
interface and their descriptors.
The
.Fn usbd_get_interface_altindex
function returns the current alternative setting index as was
specified when calling
.Fn usbd_set_interface .
The
.Fn usbd_endpoint_count
function retrieves the number of endpoints associated with the
specified interface.
The
.Fn usbd_interface2endpoint_descriptor
function returns a pointer to an in-memory endpoint descriptor for
the endpoint that has an index number of
.Fa index .
This pointer remains valid until the configuration or alternate setting
number are changed.
The function
.Fn usbd_get_endpoint_descriptor
is like
.Fn usbd_interface2endpoint_descriptor
but it accepts a
.Fa bEndpointAddress
address value instead of an index.
.Pp
The
.Fn usbd_fill_deviceinfo
function fills out a
.Vt usb_device_info
structure with information about the device.
The vendor and product names come from the device itself, falling back to
a table lookup or just providing the IDs in hexadecimal.
If
.Fa usedev
is zero then
.Fn usbd_fill_deviceinfo
will not attempt to retrieve the vendor and product names from the
device.
The usb_device_info structure is defined in
.In dev/usb/usb.h
as follows:
.Bd -literal
struct usb_device_info {
u_int8_t udi_bus;
u_int8_t udi_addr; /* device address */
usb_event_cookie_t udi_cookie;
char udi_product[USB_MAX_STRING_LEN];
char udi_vendor[USB_MAX_STRING_LEN];
char udi_release[8];
u_int16_t udi_productNo;
u_int16_t udi_vendorNo;
u_int16_t udi_releaseNo;
u_int8_t udi_class;
u_int8_t udi_subclass;
u_int8_t udi_protocol;
u_int8_t udi_config;
u_int8_t udi_speed;
#define USB_SPEED_LOW 1
#define USB_SPEED_FULL 2
#define USB_SPEED_HIGH 3
int udi_power; /* power consumption in mA */
int udi_nports;
char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
/* hub only: addresses of devices on ports */
u_int8_t udi_ports[16];
#define USB_PORT_ENABLED 0xff
#define USB_PORT_SUSPENDED 0xfe
#define USB_PORT_POWERED 0xfd
}
.Ed
.Pp
The
.Fn usbd_devinfo
function generates a string description of the USB device.
The
.Fa cp
argument should point to a 1024-byte buffer (XXX the maximum length
is approx 320 chars, but there is no sanity checking and everything uses
1024-character buffers).
Device class information is included if the
.Fa showclass
parameter is non-zero.
.Pp
The
.Fn usbd_get_quirks
function returns information from a table of devices that require
special workarounds in order to function correctly.
The returned structure is defined in
.In dev/usb/usb_quirks.h
as follows:
.Bd -literal
struct usbd_quirks {
u_int32_t uq_flags; /* Device problems */
};
.Ed
.Pp
See
.In dev/usb/usb_quirks.h
for a list of all currently defined quirks.
.Pp
USB control requests are performed via
.Vt usb_device_request_t
structures, defined in
.In dev/usb/usb.h
as follows:
.Bd -literal
typedef struct {
uByte bmRequestType;
uByte bRequest;
uWord wValue;
uWord wIndex;
uWord wLength;
} UPACKED usb_device_request_t;
.Ed
.Pp
The
.Fn usbd_do_request
function performs a single request synchronously.
The
.Fa req
parameter should point to a properly initialized
.Vt usb_device_request_t ,
and when the
.Fa wLength
field is non-zero,
.Fa data
should point at a buffer that is at least
.Fa wLength
bytes in length.
The request timeout is set to 5 seconds, so the operation will fail
with
.Er USBD_TIMEOUT
if the device does not respond within that time.
The
.Fn usbd_do_request_async
function is like
.Fn usbd_do_request ,
but it does not wait for the request to complete before returning.
This routine does not block so it can be used from contexts where
sleeping is not allowed.
Note that there is no notification mechanism to report when the
operation completed nor is there a way to determine whether the
request succeeded, so this function is of limited use.
See
.Fn usbd_setup_default_xfer
and
.Fn usbd_transfer
for a way to invoke an asynchronous callback upon completion of
a control request.
The
.Fn usbd_do_request_flags
function is like
.Fn usbd_do_request ,
but additional flags can be specified, the timeout is configurable,
and the actual number of bytes transferred is made available to the
caller.
The
.Fn usbd_do_request_flags_pipe
function uses a specified pipe instead of the default pipe.
.Pp
The function
.Fn usbd_open_pipe
creates a pipe connected to a specified endpoint on a specified interface.
The parameter
.Fa address
should be the
.Fa bEndpointAddress
value from one of this interface's endpoint descriptors.
If
.Fa flags
contains
.Dv USBD_EXCLUSIVE_USE
then the operation will only succeed if there are no open pipes
already connected to the specified endpoint.
The
.Fn usbd_open_pipe_intr
function creates an interrupt pipe connected to the specified endpoint.
The parameter
.Fa address
should be the
.Fa bEndpointAddress
value from one of this interface's endpoint descriptors.
The
.Fa flags
parameter is passed to
.Fn usbd_setup_xfer .
The
.Fa buffer
and
.Fa len
parameters define a buffer that is to be used for the interrupt transfers.
The callback to be invoked each time a transfer completes is specified by
.Fa cb ,
and
.Fa priv
is an argument to be passed to the callback function.
The
.Fa ival
parameter specifies the maximum acceptable interval between transfers;
in practice the transfers may occur more frequently.
The function
.Fn usbd_pipe2device_handle
returns the device associated with the specified
.Fa pipe .
.Pp
The
.Fn usbd_abort_pipe
function aborts all active or waiting transfers on the specified pipe.
Each transfer is aborted with a
.Dv USBD_CANCELLED
status; callback routines must detect this error code to ensure that
they do not attempt to initiate a new transfer in response to one being
aborted.
This routine blocks while it is waiting for the hardware to complete
processing of aborted transfers, so it is only safe to call it in
contexts where sleeping is allowed.
The function
.Fn usbd_abort_default_pipe
aborts all active or waiting transfers on the default pipe.
Like
.Fn usbd_abort_pipe ,
it blocks waiting for the hardware processing to complete.
.Pp
When a pipe has no active or waiting transfers, the pipe may be closed
using the
.Fn usbd_close_pipe
function.
Once a pipe is closed, its pipe handle becomes invalid and may no longer
be used.
.Pp
USB transfer handles are allocated using the function
.Fn usbd_alloc_xfer
and may be freed using
.Fn usbd_free_xfer .
.Pp
The function
.Fn usbd_setup_xfer
initializes a transfer handle with the details of a transfer to or from
a USB device.
The
.Fa xfer
parameter specifies the transfer handle to initialize,
.Fa pipe
specifies the pipe on which the transfer is to take place, and
.Fa priv
is an argument that will be passed to callback function.
The arguments
.Fa buffer
and
.Fa length
define the data buffer for the transfer.
If
.Fa length
is zero then the
.Fa buffer
may be
.Dv NULL .
The
.Fa flags
parameter may contain the following flags:
.Bl -tag -width ".Dv USBD_FORCE_SHORT_XFER"
.It Dv USBD_NO_COPY
This is used in association with
.Fn usbd_alloc_buffer
and
.Fn usbd_free_buffer
to use a dedicated DMA-capable buffer for the transfer.
.It Dv USBD_SYNCHRONOUS
Wait for the transfer to compete in
.Fn usbd_transfer .
.It Dv USBD_SHORT_XFER_OK
Permit transfers shorter than the requested data length.
.It Dv USBD_FORCE_SHORT_XFER
Force a short transfer at the end of a write operation to let the
device know that the transfer has ended.
.El
.Pp
The
.Fa timeout
parameter specifies a timeout for the transfer in milliseconds.
A value of
.Dv USBD_NO_TIMEOUT
indicates that no timeout should be configured.
The parameter
.Fa callback
specifies the function to call when the transfer completes.
Note that
.Fn usbd_setup_xfer
does not actually initiate the transfer.
The
.Fn usbd_setup_default_xfer
initializes a control transfer for the default pipe.
The
.Fa req
parameter should point at a completed
.Vt usb_device_request_t
structure.
The function
.Fa usbd_setup_isoc_xfer
initializes a transfer for an isochronous pipe.
.Pp
The function
.Fn usbd_transfer
initiates a transfer.
Normally it returns
.Dv USBD_IN_PROGRESS
to indicate that the transfer has been queued.
If the USB stack is operating in polling mode, or if the transfer
is synchronous, then
.Dv USBD_NORMAL_COMPLETION
may be returned.
Other return values indicate that the transfer could not be
initiated due to an error.
The
.Fn usbd_sync_transfer
function executes a transfer synchronously.
It will sleep waiting for the transfer to complete and then return
the transfer status.
Note that if the transfer has a callback routine, this will be
invoked before
.Fn usbd_sync_transfer
returns.
.Pp
The
.Fn usbd_intr_transfer
and
.Fn usbd_bulk_transfer
functions set up a transfer and wait synchronously for it to complete
but they allows signals to interrupt the wait.
They returns
.Dv USBD_INTERRUPTED
if the transfer was interrupted by a signal.
XXX these two functions are identical apart from their names.
.Pp
The function
.Fn usbd_get_xfer_status
retrieves various information from a completed transfer.
If the
.Fa priv
parameter is not NULL then the callback private argument is
stored in
.Fa *priv .
If
.Fa buffer
is not NULL then the transfer buffer pointer is stored in
.Fa *buffer .
The actual number of bytes transferred is stored in
.Fa *count
if
.Fa count is not NULL.
Finally, the transfer status is stored in
.Fa *status
if
.Fa status
is not NULL.
.Pp
The
.Fn usbd_clear_endpoint_stall
function clears an endpoint stall condition synchronously, i.e.\&
it sleeps waiting for the stall clear request to complete.
The function
.Fn usbd_clear_endpoint_stall_async
performs the same function asynchronously, but it provides no
way to determine when the request completed, or whether it was
successful.
The
.Fn usbd_clear_endpoint_toggle
function instructs the host controller driver to reset the toggle bit
on a pipe.
This is used when manually clearing an endpoint stall using a
control pipe request, in order to ensure that the host controller
driver and the USB device restart with the same toggle value.
.Pp
Normally the USB subsystem maps and copies data to and from
DMA-capable memory each time a transfer is performed.
The function
.Fn usbd_alloc_buffer
allocates a permanent DMA-capable buffer associated with the
transfer to avoid this overhead.
The return value is the virtual address of the buffer.
Any time that
.Fn usbd_setup_xfer
is called on the transfer with the
.Dv USBD_NO_COPY
flag enabled, the allocated buffer will be used directly and
the
.Fa buffer
argument passed to
.Fn usbd_setup_xfer
will be ignored.
The
.Fn usbd_get_buffer
function returns a pointer to the virtual address of a buffer previously
allocated by
.Fn usbd_alloc_buffer .
Finally,
.Fn usbd_free_buffer
deallocates the buffer.
.Pp
The
.Fn usbd_errstr
function converts a status code into a string for display.
.Pp
The function
.Fn usbd_set_polling
enables or disables polling mode.
In polling mode, all operations will busy-wait for the device to
respond, so its use is effectively limited to boot time and kernel
debuggers.
It is important to match up calls that enable and disable polling
mode, because the implementation just increments a polling reference
count when
.Fa on
is non-zero and decrements it when
.Fa on
is zero.
The
.Fn usbd_dopoll
causes the host controller driver to poll for any activity.
This should only be used when polling mode is enabled.
.Pp
The
.Fn usbd_ratecheck
function is used to limit the rate at which error messages are
printed to approximately once per second.
The
.Fa last
argument should point at a persistent
.Vt "struct timeval" .
A value of 1 will be returned if a message should be printed, but if
.Fn usbd_ratecheck
has already been called with the same
.Vt "struct timeval"
parameter in the last second then 0 is returned and the error message
should be suppressed.
.Pp
The functions
.Fn usb_detach_wait
and
.Fn usb_detach_wakeup
are used to wait for references to drain before completing the
detachment of a device.
The
.Fn usb_detach_wait
function will wait up to 60 seconds to receive a signal from
.Fn usb_detach_wait .
.Ss "USB Descriptors"
The USB specification defines a number of standard descriptors by
which USB devices report their attributes.
These descriptors are fixed-format structures that all USB devices
make available through USB control pipe requests.
.Pp
Every USB device has exactly one USB device descriptor.
The USB subsystem retrieves this automatically when a device is
attached, and a copy of the descriptor is kept in memory.
The
.Fn usbd_get_device_descriptor
function returns a pointer to the descriptor.
The device descriptor structure is defined in
.In dev/usb/usb.h
as follows:
.Bd -literal
typedef struct {
uByte bLength;
uByte bDescriptorType;
uWord bcdUSB;
#define UD_USB_2_0 0x0200
#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0)
uByte bDeviceClass;
uByte bDeviceSubClass;
uByte bDeviceProtocol;
uByte bMaxPacketSize;
/* The fields below are not part of the initial descriptor. */
uWord idVendor;
uWord idProduct;
uWord bcdDevice;
uByte iManufacturer;
uByte iProduct;
uByte iSerialNumber;
uByte bNumConfigurations;
} UPACKED usb_device_descriptor_t;
#define USB_DEVICE_DESCRIPTOR_SIZE 18
.Ed
.Pp
USB devices have at least one configuration descriptor.
The
.Fa bNumConfigurations
field of the device descriptor specifies the number of configuration
descriptors that a device supports.
The
.Fn usbd_get_config_desc
function retrieves a particular configuration descriptor from the device
and the
.Fn usbd_get_config_desc_full
function retrieves a full
.Fa wTotalLength
length configuration descriptor, which includes all related interface
and endpoint descriptors.
Only one configuration may be active at a time.
The
.Fn usbd_set_config_index
function activates a specified configuration.
The configuration descriptor structure is defined in
.In dev/usb/usb.h
as follows:
.Bd -literal
typedef struct {
uByte bLength;
uByte bDescriptorType;
uWord wTotalLength;
uByte bNumInterface;
uByte bConfigurationValue;
uByte iConfiguration;
uByte bmAttributes;
#define UC_BUS_POWERED 0x80
#define UC_SELF_POWERED 0x40
#define UC_REMOTE_WAKEUP 0x20
uByte bMaxPower; /* max current in 2 mA units */
#define UC_POWER_FACTOR 2
} UPACKED usb_config_descriptor_t;
#define USB_CONFIG_DESCRIPTOR_SIZE 9
.Ed
.Pp
Each device configuration provides one or more interfaces.
The
.Fa bNumInterface
field of the configuration descriptor specifies the number of
interfaces associated with a device configuration.
Interfaces are described by an interface descriptor, which is defined in
.In dev/usb/usb.h
as follows:
.Bd -literal
typedef struct {
uByte bLength;
uByte bDescriptorType;
uByte bInterfaceNumber;
uByte bAlternateSetting;
uByte bNumEndpoints;
uByte bInterfaceClass;
uByte bInterfaceSubClass;
uByte bInterfaceProtocol;
uByte iInterface;
} UPACKED usb_interface_descriptor_t;
#define USB_INTERFACE_DESCRIPTOR_SIZE 9
.Ed
.Pp
Configurations may also have alternate interfaces with the same
.Fa bInterfaceNumber
but different
.Fa bAlternateSetting
values.
These alternate interface settings may be selected by passing a
non-zero
.Fa altidx
parameter to
.Fn usbd_set_interface .
.Pp
Interfaces have zero or more endpoints, and each endpoint has an
endpoint descriptor.
Note that endpoint zero, which is always present, does not have an
endpoint descriptor, and it is never included in the
.Fa bNumEndpoints
count of endpoints.
The endpoint descriptor is defined in
.In dev/usb/usb.h
as follows:
.Bd -literal
typedef struct {
uByte bLength;
uByte bDescriptorType;
uByte bEndpointAddress;
#define UE_GET_DIR(a) ((a) & 0x80)
#define UE_SET_DIR(a,d) ((a) | (((d)&1) << 7))
#define UE_DIR_IN 0x80
#define UE_DIR_OUT 0x00
#define UE_ADDR 0x0f
#define UE_GET_ADDR(a) ((a) & UE_ADDR)
uByte bmAttributes;
#define UE_XFERTYPE 0x03
#define UE_CONTROL 0x00
#define UE_ISOCHRONOUS 0x01
#define UE_BULK 0x02
#define UE_INTERRUPT 0x03
#define UE_GET_XFERTYPE(a) ((a) & UE_XFERTYPE)
#define UE_ISO_TYPE 0x0c
#define UE_ISO_ASYNC 0x04
#define UE_ISO_ADAPT 0x08
#define UE_ISO_SYNC 0x0c
#define UE_GET_ISO_TYPE(a) ((a) & UE_ISO_TYPE)
uWord wMaxPacketSize;
uByte bInterval;
} UPACKED usb_endpoint_descriptor_t;
#define USB_ENDPOINT_DESCRIPTOR_SIZE 7
.Ed
.Sh RETURN VALUES
Many functions return a
.Vt usbd_status
type to indicate the outcome of the operation.
If the operation completed successfully then
.Dv USBD_NORMAL_COMPLETION
is returned.
Operations that have been started but not yet completed will return
.Dv USBD_IN_PROGRESS .
Other errors usually indicate a problem.
Error codes can be converted to strings using
.Fn usbd_errstr .
.Sh ERRORS
.Bl -tag -width ".Er USBD_PENDING_REQUESTS"
.It Bq Er USBD_PENDING_REQUESTS
A pipe could not be closed because there are active requests.
.It Bq Er USBD_NOT_STARTED
The transfer has not yet been started.
.It Bq Er USBD_INVAL
An invalid value was supplied.
.It Bq Er USBD_NOMEM
An attempt to allocate memory failed.
.It Bq Er USBD_CANCELLED
The transfer was aborted.
.It Bq Er USBD_BAD_ADDRESS
The specified endpoint address was not found.
.It Bq Er USBD_IN_USE
The endpoint is already in use, or the configuration cannot be changed
because some of its endpoints are in use.
.It Bq Er USBD_NO_ADDR
No free USB devices addresses were found to assign to the device.
.It Bq Er USBD_SET_ADDR_FAILED
The device address could not be set.
.It Bq Er USBD_NO_POWER
Insufficient power was available for the device.
.It Bq Er USBD_TOO_DEEP
Too many levels of chained hubs were found.
.It Bq Er USBD_IOERROR
There was an error communicating with the device.
.It Bq Er USBD_NOT_CONFIGURED
An operation that requires an active configuration was attempted while
the device was in an unconfigured state.
.It Bq Er USBD_TIMEOUT
A transfer timed out.
.It Bq Er USBD_SHORT_XFER
A transfer that disallowed short data lengths completed with less than
the requested length transferred.
.It Bq Er USBD_STALLED
A transfer failed because the pipe is stalled.
.It Bq Er USBD_INTERRUPTED
An interruptible operation caught a signal.
.El
.Sh SEE ALSO
.Xr usb 4
.Sh HISTORY
The USB driver interface first appeared in
.Fx 3.0 .
.Sh AUTHORS
The USB driver was written by
.An Lennart Augustsson
for the
.Nx
project.
.Pp
.An -nosplit
This manual page was written by
.An Ian Dowse Aq iedowse@FreeBSD.org .