diff options
author | iedowse <iedowse@FreeBSD.org> | 2005-12-31 03:53:02 +0000 |
---|---|---|
committer | iedowse <iedowse@FreeBSD.org> | 2005-12-31 03:53:02 +0000 |
commit | 1edbd8766fcb57f6687dfffc86450b2b8faef66e (patch) | |
tree | 7930f5793e4978d6c3d4ab565b2faae253d169e5 /share | |
parent | deb09036e824eb9221944cd1227aeb23e23dda6c (diff) | |
download | FreeBSD-src-1edbd8766fcb57f6687dfffc86450b2b8faef66e.zip FreeBSD-src-1edbd8766fcb57f6687dfffc86450b2b8faef66e.tar.gz |
Add basic documentation for many of the kernel USB functions that
USB device drivers use to talk to USB devices. This is probably
still a bit rough and it does not yet include the functions specific
to HID, ethernet, hubs, host controller drivers, task threads or
debugging.
Diffstat (limited to 'share')
-rw-r--r-- | share/man/man9/Makefile | 50 | ||||
-rw-r--r-- | share/man/man9/usbdi.9 | 1253 |
2 files changed, 1303 insertions, 0 deletions
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 4a8531a..1bfb27d 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -219,6 +219,7 @@ MAN= accept_filter.9 \ ucred.9 \ uidinfo.9 \ uio.9 \ + usbdi.9 \ utopia.9 \ vaccess.9 \ vaccess_acl_posix1e.9 \ @@ -969,6 +970,55 @@ MLINKS+=uidinfo.9 uifind.9 \ uidinfo.9 uihashinit.9 \ uidinfo.9 uihold.9 MLINKS+=uio.9 uiomove.9 +MLINKS+=usbdi.9 usb_find_desc.9 \ + usbdi.9 usbd_abort_default_pipe.9 \ + usbdi.9 usbd_abort_pipe.9 \ + usbdi.9 usbd_alloc_buffer.9 \ + usbdi.9 usbd_alloc_xfer.9 \ + usbdi.9 usbd_clear_endpoint_stall.9 \ + usbdi.9 usbd_clear_endpoint_stall_async.9 \ + usbdi.9 usbd_clear_endpoint_toggle.9 \ + usbdi.9 usbd_close_pipe.9 \ + usbdi.9 usbd_device2interface_handle.9 \ + usbdi.9 usbd_do_request.9 \ + usbdi.9 usbd_do_request_async.9 \ + usbdi.9 usbd_do_request_flags.9 \ + usbdi.9 usbd_do_request_flags_pipe.9 \ + usbdi.9 usbd_endpoint_count.9 \ + usbdi.9 usbd_errstr.9 \ + usbdi.9 usbd_find_edesc.9 \ + usbdi.9 usbd_find_idesc.9 \ + usbdi.9 usbd_free_buffer.9 \ + usbdi.9 usbd_free_xfer.9 \ + usbdi.9 usbd_get_buffer.9 \ + usbdi.9 usbd_get_config.9 \ + usbdi.9 usbd_get_config_desc.9 \ + usbdi.9 usbd_get_config_desc_full.9 \ + usbdi.9 usbd_get_config_descriptor.9 \ + usbdi.9 usbd_get_device_descriptor.9 \ + usbdi.9 usbd_get_endpoint_descriptor.9 \ + usbdi.9 usbd_get_interface_altindex.9 \ + usbdi.9 usbd_get_interface_descriptor.9 \ + usbdi.9 usbd_get_no_alts.9 \ + usbdi.9 usbd_get_quirks.9 \ + usbdi.9 usbd_get_speed.9 \ + usbdi.9 usbd_get_string.9 \ + usbdi.9 usbd_get_string_desc.9 \ + usbdi.9 usbd_get_xfer_status.9 \ + usbdi.9 usbd_interface2device_handle.9 \ + usbdi.9 usbd_interface2endpoint_descriptor.9 \ + usbdi.9 usbd_interface_count.9 \ + usbdi.9 usbd_open_pipe.9 \ + usbdi.9 usbd_open_pipe_intr.9 \ + usbdi.9 usbd_pipe2device_handle.9 \ + usbdi.9 usbd_set_config_index.9 \ + usbdi.9 usbd_set_config_no.9 \ + usbdi.9 usbd_set_interface.9 \ + usbdi.9 usbd_setup_default_xfer.9 \ + usbdi.9 usbd_setup_isoc_xfer.9 \ + usbdi.9 usbd_setup_xfer.9 \ + usbdi.9 usbd_sync_transfer.9 \ + usbdi.9 usbd_transfer.9 MLINKS+=vcount.9 count_dev.9 MLINKS+=vfsconf.9 vfs_modevent.9 \ vfsconf.9 vfs_register.9 \ diff --git a/share/man/man9/usbdi.9 b/share/man/man9/usbdi.9 new file mode 100644 index 0000000..ee640bb --- /dev/null +++ b/share/man/man9/usbdi.9 @@ -0,0 +1,1253 @@ +.\" +.\" 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 . |