Transfers are either synchronous or asynchronous. Synchronous transfers block until they complete. Asynchronous transfers callback into the client driver when they complete. Most transfer functions called with the USB_FLAGS_SLEEP flag set in the flags argument are synchronous.
Continuous transfers such as polling and isochronous transfers cannot be synchronous. Calls to transfer functions for continuous transfers made with the USB_FLAGS_SLEEP flag set block only to wait for resources before the transfer begins.
Synchronous transfers are the most simple transfers to set up because synchronous transfers do not require any callback functions. Synchronous transfer functions return a transfer start status, even though synchronous transfer functions block until the transfer is completed. Upon completion, you can find additional information about the transfer status in the completion reason field and callback flags field of the request. Completion reasons and callback flags fields are discussed below.
If the USB_FLAGS_SLEEP flag is not specified in the flags argument, that transfer operation is asynchronous. The exception to this rule are isochronous transfers. Asynchronous transfer operations set up and start the transfer, and then return before the transfer is complete. Asynchronous transfer operations return a transfer start status. The client driver receives transfer completion status through callback handlers.
Callback handlers are functions that are called when asynchronous transfers complete. Do not set up an asynchronous transfer without callbacks. The two types of callback handlers are normal completion handlers and exception handlers. You can specify one handler to be called in both of these cases.
Normal completion. A normal completion callback handler is called to notify of a normally completed transfer.
Exception. An exception callback handler is called to notify of an abnormally completed transfer and to process its errors.
Both completion handlers and exception handlers receive the transfer's request as an argument. Exception handlers use the completion reason and callback status in the request to find out what happened. The completion reason (usb_cr_t) indicates how the original transaction completed. For example, a completion reason of USB_CR_TIMEOUT indicates that the transfer timed out. As another example, if a USB device is removed while in use, client drivers might receive USB_CR_DEV_NOT_RESP as the completion reason on their outstanding requests. The callback status (usb_cb_flags_t) indicates what the USBA framework did to remedy the situation. For example, a callback status of USB_CB_STALL_CLEARED indicates that the USBA framework cleared a functional stall condition. See the usb_completion_reason(9S) man page for more information on completion reasons. See the usb_callback_flags(9S) man page for more information on callback status flags.
Callback context. Most callbacks execute in kernel context and usually can block. Some callbacks execute in interrupt context and cannot block. The USB_CB_INTR_CONTEXT flag is set in the callback flags to denote interrupt context. See the usb_callback_flags(9S) man page for more information on callback context and details on blocking.
Pipe policy. The pipe policy's hint on concurrent asynchronous operations limits the number of operations that can be run in parallel, including those executed from a callback handler. Blocking on a synchronous operation counts as one operation. See the usb_pipe_open(9F) man page for more information on pipe policy.