summaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2005-12-31 03:53:02 +0000
committeriedowse <iedowse@FreeBSD.org>2005-12-31 03:53:02 +0000
commit1edbd8766fcb57f6687dfffc86450b2b8faef66e (patch)
tree7930f5793e4978d6c3d4ab565b2faae253d169e5 /share
parentdeb09036e824eb9221944cd1227aeb23e23dda6c (diff)
downloadFreeBSD-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/Makefile50
-rw-r--r--share/man/man9/usbdi.91253
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 .
OpenPOWER on IntegriCloud