usba_hcdi_pipe_ctrl_xfer - perform a USB control transfer


#include <sys/usb/usba/hcdi.h>

prefix_hcdi_pipe_ctrl_xfer(usba_pipe_handle_data_t *ph,
usb_ctrl_req_t *ucrp, usb_flags_t usb_flags);


Volatile - illumos USB HCD private function

This is a private function that is not part of the stable DDI. It may be
removed or changed at any time.


ph A pointer to a USB pipe handle as defined in

ucrp A pointer to a USB control transfer request. The structure's
members are documented in usb_ctrl_req(9S).

usb_flags Flags which describe how allocations should be performed.
Valid flags are:

Do not block waiting for memory. If memory is not
available the allocation will fail.

Perform a blocking allocation. If memory is not
available, the function will wait until memory is
made available.

Note, the request may still fail even if
USB_FLAGS_SLEEP is specified.


The usba_hcdi_pipe_ctrl_xfer() entry point is used to initiate an
asynchronous USB Control transfer on the pipe ph. The specific USB control
transfer is provided in ucrp. For more background on transfer types, see

The host controller driver should first check the USB address of the pipe
handle. It may correspond to the root hub. If it does, rather than
initiating an I/O transfer, the driver may need to emulate it using
available information.

Control endpoints are always bi-directional. A given endpoint may perform
transfer data from the OS to the device, or from the device to the OS. The
driver will need to look at the control transfer request and transform that
into the appropriate format for the controller.

Control transfers are made up of three parts. A setup stage, an optional
data stage, and a status stage. Depending on the controller, the driver
may need to transform the transfer request into a format that matches this.
Refer to the device's controller specification for more information on
whether this is required or not.

The device driver should a request based on the information present in the
control request ucrp. If there is a non-zero length for the transfer,
indicated by the ctrl_wLength member of ucrp being greater than zero, then
the controller needs to allocate a separate memory buffer for the request.
The corresponding data will be found in an mblk(9S) structure as the
ctrl_data member of ucrp.

If this transfer needs to be sent to a device through the controller and is
not being handled directly by the driver, then the driver should allocate a
separate region of memory (generally memory suitable for a DMA transfer)
for the transfer. If sending data to the device, the data in the message
block should be copied prior to the transfer. Otherwise, once the transfer
completes, data should be transferred into the message block and the write
pointer incremented.

If the driver needs to allocate memory for this transfer, it should honor
the values set in usb_flags to indicate whether or not it should block for
memory, whether DMA memory or normal kernel memory.

If the driver successfully schedules the I/O or it can handle the I/O
itself because it's a synthetic root hub request, then it should return
USB_SUCCESS. If the driver returns successfully, it must call
usba_hcdi_cb(9F) with ucrp either before or after it returns. The only
times that a driver would call the callback before the function returns are
for requests to the root hub that it handles inline and does not need to
send off asynchronous activity to the controller.

For asynchronous requests, the controller is also responsible for timing
out the request if it does not complete. If the timeout in the request as
indicated in the ctrl_timeout member is set to zero, then the driver should
use the USBA default timeout of HCDI_DEFAULT_TIMEOUT. All timeout values
are in seconds.

Callback Handling

When the control transfer completes the driver should consider the
following items to determine what actions it should take on the callback:

+o If the transfer timed out, it should remove the transfer from the
outstanding list, queue the next transfer, and return the transfer back
to the OS with the error code USB_CR_TIMEOUT with usba_hcdi_cb(9F).

+o If the transfer failed, it should find the appropriate error and call
usba_hcdi_cb(9F) with that error.

+o If the transfer succeeded, but less data was transferred than expected,
consult the ctrl_attributes member of the ucrp. If the
USB_ATTRS_SHORT_XFER_OK flag is not present, then the driver should
call usba_hcdi_cb(9F) with the error USB_CR_DATA_UNDERRUN.

+o If the transfer was going to the host, then the driver should copy the
data into the transfer's message block and update the b_wptr member of
the mblk(9S).

+o If everything was successful, call usba_hcdi_cb(9F) with the code


Upon successful completion, the usba_hcdi_pipe_ctrl_xfer() function should
return USB_SUCCESS. Otherwise, it should return the appropriate USB error.
If uncertain, use USB_FAILURE.


usba_hcdi(9E), usba_hcdi_cb(9F), mblk(9S), usb_ctrl_req(9S),

OmniOS December 22, 2016 OmniOS