USB_PIPE_CTRL_XFER(9F) | Kernel Functions for Drivers | USB_PIPE_CTRL_XFER(9F) |
usb_pipe_ctrl_xfer, usb_pipe_ctrl_xfer_wait - USB control pipe transfer functions
#include <sys/usb/usba.h> int usb_pipe_ctrl_xfer(usb_pipe_handle_t pipe_handle,
usb_ctrl_req_t *request, usb_flags_t flags);
int usb_pipe_ctrl_xfer_wait(usb_pipe_handle_t pipe_handle,
usb_ctrl_setup_t *setup, mblk_t **data,
usb_cr_t * completion_reason, usb_cb_flags_t *cb_flags,
usb_flags_t flags);
illumos DDI specific (illumos DDI)
For usb_pipe_ctrl_xfer():
pipe_handle
request
flags
For usb_pipe_ctrl_xfer_wait():
pipe_handle
setup
data
completion_reason
callback_flags
flags
The usb_pipe_ctrl_xfer() function requests the USBA framework to perform a transfer through a USB control pipe. The request is passed to the host controller driver (HCD), which performs the necessary transactions to complete the request. Requests are synchronous when USB_FLAGS_SLEEP is specified in flags; calls for synchronous requests do not return until their transaction is completed. Asynchronous requests (made without specifying the USB_FLAGS_SLEEP flag) notifies the caller of their completion via a callback function.
The usb_pipe_ctrl_xfer_wait() function is a wrapper around usb_pipe_ctrl_xfer() that performs allocation and deallocation of all required data structures, and a synchronous control-pipe transfer. It takes a usb_ctrl_setup_t containing most usb setup parameters as an argument:
uchar_t bmRequestType /* characteristics of request. */
/* (See USB 2.0 spec, section 9.3). */
/* Combine one direction of: */
/* USB_DEV_REQ_HOST_TO_DEV */
/* USB_DEV_REQ_DEV_TO_HOST */
/* with one request type of: */
/* USB_DEV_REQ_TYPE_STANDARD */
/* USB_DEV_REQ_TYPE_CLASS */
/* USB_DEV_REQ_TYPE_VENDOR */
/* with one recipient type of: */
/* USB_DEV_REQ_RCPT_DEV */
/* USB_DEV_REQ_RCPT_IF */
/* USB_DEV_REQ_RCPT_EP */
/* USB_DEV_REQ_RCPT_OTHER. */
uchar_t bRequest /* request or command. */
/* (See USB 2.0 spec, section */
/* 9.3 for standard commands.) */
uint16_t wValue /* value which varies according to */
/* the command (bRequest). */
uint16_t wIndex /* value which varies according to */
/* the command, typically used to */
/* pass an index or offset. */
uint16_t wLength /* number of data bytes to transfer */
/* with command, if any. Same as */
/* size of mblk "data" below. */
usb_req_attrs_t attrs; /* required request attributes */
Please see usb_request_attributes(9S), or refer to Section 5.5 of the USB 2.0 specification for more information on these parameters. (The USB 2.0 specification is available at www.usb.org.)
Mblks for data are allocated optionally when a request is allocated via usb_alloc_ctrl_req(9F) by passing a positive value for the len argument. Control requests passing or receiving no supplemental data need not allocate an mblk.
For usb_pipe_ctrl_xfer():
USB_SUCCESS
USB_INVALID_ARGS
USB_INVALID_CONTEXT
USB_INVALID_REQUEST
A set of conflicting attributes were specified. See usb_request_attributes(9S).
The normal and/or exception callback is NULL and USB_FLAGS_SLEEP is not set.
Data space not provided to a control request while ctrl_wLength is nonzero.
USB_INVALID_PIPE
Pipe is closing or closed.
USB_NO_RESOURCES
USB_HC_HARDWARE_ERROR
USB_FAILURE
The pipe is in an unsuitable state (error, busy, not ready).
Additional status information may be available in the ctrl_completion_reason and ctrl_cb_flags fields of the request. Please see usb_callback_flags(9S) and usb_completion_reason(9S) for more information.
For usb_pipe_ctrl_xfer_wait():
USB_SUCCESS
USB_INVALID_CONTEXT
USB_INVALID_ARGS
Any error code returned by usb_pipe_ctrl_xfer().
Additional status information may be available in the ctrl_completion_reason and ctrl_cb_flags fields of the request. Please see usb_callback_flags(9S) and usb_completion_reason(9S) for more information.
The usb_pipe_ctrl_xfer() function may be called from kernel or user context without regard to arguments and from the interrupt context only when the USB_FLAGS_SLEEP flag is clear.
The usb_pipe_ctrl_xfer_wait() function may be called from kernel or user context.
/* Allocate, initialize and issue a synchronous control request. */
usb_ctrl_req_t ctrl_req;
void control_pipe_exception_callback(
usb_pipe_handle_t, usb_ctrl_req_t*);
ctrl_req = usb_alloc_ctrl_req(dip, 0, USB_FLAGS_SLEEP);
ctrl_req->ctrl_bmRequestType = USB_DEV_REQ_HOST_TO_DEV |
USB_DEV_REQ_TYPE_CLASS | USB_DEV_REQ_RCPT_OTHER;
ctrl_req->ctrl_bRequest = (uint8_t)USB_PRINTER_SOFT_RESET;
ctrl_req->ctrl_exc_cb = control_pipe_exception_callback;
...
...
if ((rval = usb_pipe_ctrl_xfer(pipe, ctrl_req, USB_FLAGS_SLEEP))
!= USB_SUCCESS) {
cmn_err (CE_WARN, "%s%d: Error issuing USB cmd.",
ddi_driver_name(dip), ddi_get_instance(dip));
}
-------
/*
* Allocate, initialize and issue an asynchronous control request to
* read a configuration descriptor.
*/
usb_ctrl_req_t *ctrl_req;
void control_pipe_normal_callback(
usb_pipe_handle_t, usb_ctrl_req_t*);
void control_pipe_exception_callback(
usb_pipe_handle_t, usb_ctrl_req_t*);
struct buf *bp = ...;
ctrl_req =
usb_alloc_ctrl_req(dip, sizeof(usb_cfg_descr_t), USB_FLAGS_SLEEP);
ctrl_req->ctrl_bmRequestType = USB_DEV_REQ_DEV_TO_HOST |
USB_DEV_REQ_TYPE_STANDARD | USB_DEV_REQ_RCPT_DEV;
ctrl_req->ctrl_wLength = sizeof(usb_cfg_descr_t);
ctrl_req->ctrl_wValue = USB_DESCR_TYPE_SETUP_CFG | 0;
ctrl_req->ctrl_bRequest = (uint8_t)USB_REQ_GET_DESCR;
ctrl_req->ctrl_cb = control_pipe_normal_callback;
ctrl_req->ctrl_exc_cb = control_pipe_exception_callback;
/* Make buf struct available to callback handler. */
ctrl_req->ctrl_client_private = (usb_opaque_t)bp;
...
...
if ((rval = usb_pipe_ctrl_xfer(pipe, ctrl_req, USB_FLAGS_NOSLEEP))
!= USB_SUCCESS) {
cmn_err (CE_WARN, "%s%d: Error issuing USB cmd.",
ddi_driver_name(dip), ddi_get_instance(dip));
}
-------
/* Call usb_pipe_ctrl_xfer_wait() to get device status. */
mblk_t *data;
usb_cr_t completion_reason;
usb_cb_flags_t callback_flags;
usb_ctrl_setup_t setup_params = {
USB_DEV_REQ_DEV_TO_HOST | /* bmRequestType */
USB_DEV_REQ_TYPE_STANDARD | USB_DEV_REQ_RCPT_DEV,
USB_REQ_GET_STATUS, /* bRequest */
0, /* wValue */
0, /* wIndex */
USB_GET_STATUS_LEN, /* wLength */
0 /* attributes. */
};
if (usb_pipe_ctrl_xfer_wait(
pipe,
&setup_params,
&data,
&compleetion_reason,
&callback_flags,
0) != USB_SUCCESS) {
cmn_err (CE_WARN,
"%s%d: USB get status command failed: "
"reason=%d callback_flags=0x%x",
ddi_driver_name(dip), ddi_get_instance(dip),
completion_reason, callback_flags);
return (EIO);
}
/* Check data length. Should be USB_GET_STATUS_LEN (2 bytes). */
length_returned = data->b_wptr - data->b_rptr;
if (length_returned != USB_GET_STATUS_LEN) {
cmn_err (CE_WARN,
"%s%d: USB get status command returned %d bytes of data.",
ddi_driver_name(dip), ddi_get_instance(dip), length_returned);
return (EIO);
}
/* Retrieve data in endian neutral way. */
status = (*(data->b_rptr + 1) << 8) | *(data->b_rptr);
See attributes(7) for descriptions of the following attributes:
ATTRIBUTE TYPE | ATTRIBUTE VALUE |
Architecture | PCI-based systems |
Interface stability | Committed |
attributes(7), usb_alloc_request(9F), usb_get_cfg(9F), usb_get_status(9F), usb_pipe_bulk_xfer(9F), usb_pipe_get_state(9F), usb_pipe_intr_xfer(9F), usb_pipe_isoc_xfer(9F), usb_pipe_reset(9F), usb_pipe_xopen(9F), usb_bulk_request(9S), usb_callback_flags(9S), usb_completion_reason(9S), usb_ctrl_request(9S), usb_intr_request(9S), usb_isoc_request(9S)
September 16, 2016 | OmniOS |