Copyright (c) 2006, Sun Microsystems, Inc., All Rights Reserved
The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
#include <sys/usb/usba.h> int usb_pipe_intr_xfer(usb_pipe_handle_t pipe_handle, usb_intr_req_t *request, usb_flags_t flags);
void usb_pipe_stop_intr_polling(usb_pipe_handle_t pipe_handle, usb__flags_t flags);
Interrupt pipe handle on which request is made.
Pointer to interrupt transfer request.
USB_FLAGS_SLEEP is the only flag recognized. Wait for needed resources if unavailable. For requests specifying the USB_ATTRS_ONE_XFER attribute, wait for the request to complete.
For usb_pipe_stop_intr_polling(): pipe_handle
Interrupt pipe handle on which to stop polling for data.
USB_FLAGS_SLEEP is the only flag recognized. Wait for polling to stop.
There are three categories of interrupt transfers: periodic or polled interrupt-IN, single-transfer interrupt-IN, and (single-transfer) interrupt-OUT.
Periodic interrupt-IN transfers are always asynchronous. Client driver notification of new data is always via a callback. The USB_FLAGS_SLEEP flag is only to wait for resources to become available. Callbacks must always be in place to receive transfer completion notification. Please see usb_callback_flags(9S) for details on USB callbacks.
Calls made to usb_pipe_intr_xfer() for starting input polling need allocate only one request. The USBA framework allocates a new request each time polling has new data to return. (Note that each request returned must be freed via usb_free_intr_req(9F). Specify a zero length when calling usb_alloc_intr_req() to allocate the original request, since it will not be used to return data. Set the intr_len in the request to specify how much data can be returned per polling interval.
The original request passed to usb_pipe_intr_xfer() is used to return status when polling is terminated, or on an error condition when the USB_ATTRS_AUTOCLEARING attribute is set for the request. If autoclearing is not set, the current (non-original) request is returned on error. Call usb_pipe_reset(9F) to reset the pipe and get back the original request in this case. The USB_CR_STOPPED_POLLING flag is always set for callbacks where the original request is returned.
Interrupt-OUT transfers are synchronous when the USB_FLAGS_SLEEP flag is set in the request's flags. Calls for synchronous transfers will not return until their transaction has completed. Calls for asynchronous transfers notify the client driver of transaction completion via a normal callback, or error completion via an exception callback.
The usb_pipe_stop_intr_polling() function terminates polling on interrupt-IN pipes and does the following:
1. Cease polling.
2. Allow any requests-in-progress to complete and be returned to the client driver through the normal callback mechanism.
3. Idle the pipe.
4. Return the original polling request to the client driver through an exception callback with a completion reason of USB_CR_STOPPED_POLLING.
The client driver may restart polling from an exception callback only if the callback corresponds to an original request. The callback handler checks for the following completion reasons to ensure that a callback corresponds to an original request:
USB_CR_STOPPED_POLLING, USB_CR_PIPE_RESET, USB_CR_PIPE_CLOSING, USB_CR_NOT_SUPPORTED
The callback handler also checks the request's intr_data field to mark original polling requests, when the requests are created with a zero len argument. In this case, a NULL intr_data field distinguishes a returned original request from a request allocated by the framework during polling.
Mblks for data for interrupt-OUT requests are allocated when a request is allocated via usb_alloc_intr_req(9F) by passing a non-negative value for the len argument.
Transfer was successful.
Request is NULL.
Called from interrupt context with the USB_FLAGS_SLEEP flag set.
The request has been freed or otherwise invalidated. A set of conflicting attributes was specified. See usb_intr_request(9S). The normal and/or exception callback was NULL, USB_FLAGS_SLEEP was not set and USB_ATTRS_ONE_XFER was not set. An interrupt request was specified with a NULL data and a non-zero intr_len value. An IN interrupt request was specified with both polling (USB_ATTRS_ONE_XFER clear in attributes) and non-zero timeout specified. An IN interrupt request was specified with a non-NULL data argument. An OUT interrupt request was specified with a NULL data argument.
Pipe handle is NULL or invalid. Pipe is closing or closed.
Pipe handle refers to a pipe which is in the USB_PIPE_STATE_ERROR state.
Memory, descriptors or other resources unavailable.
Host controller is in error state.
An asynchronous transfer failed or an internal error occurred. An intr polling request is made while polling is already in progress. The pipe is in an unsuitable state (error, busy, not ready). Additional status information may be available in the intr_completion_reason and intr_cb_flags fields of the request. Please see usb_completion_reason(9S) and usb_callback_flags(9S) for more information.
For usb_pipe_stop_intr_polling()
None, but fails if called with USB_FLAGS_SLEEP specified from interrupt context, pipe handle is invalid, NULL or pertains to a closing or closed pipe, or the pipe is in an error state. Error messages are logged to the console logfile.
Exception handlers' queued requests which are flushed by these commands before execution are returned with completion reason of USB_CR_FLUSHED.
/* Start polling on interrupt-IN pipe. */ usb_intr_req_t intr_req; void intr_pipe_callback(usb_pipe_handle_t, usb_intr_req_t*); void intr_pipe_exception_callback( usb_pipe_handle_t, usb_intr_req_t*); usb_ep_descr_t *ep_descr; ep_descr = ...; intr_req = usb_alloc_intr_req(dip, 0, USB_FLAGS_SLEEP); ... ... intr_req->intr_attributes = USB_ATTRS_SHORT_XFER_OK; intr_req->intr_len = ep_descr->wMaxPacketSize; ... ... intr_req->intr_cb = intr_pipe_callback; intr_req->intr_exc_cb = intr_pipe_exception_callback; if ((rval = usb_pipe_intr_xfer(pipe, intr_req, USB_FLAGS_NOSLEEP)) != USB_SUCCESS) { cmn_err (CE_WARN, "%s%d: Error starting interrupt pipe polling.", ddi_driver_name(dip), ddi_get_instance(dip)); } ------- /* Stop polling before setting device idle. Wait for polling to stop. */ usb_pipe_stop_intr_polling(pipe, USB_FLAGS_SLEEP); (void) pm_idle_component(dip, 0); ------- /* Allocate, initialize and issue a synchronous intr-OUT request. */ usb_intr_req_t intr_req; mblk_t *mblk; usb_ep_descr_t *ep_descr; ep_descr = ...; intr_req = usb_alloc_intr_req(dip, ep_descr->wMaxPacketSize, USB_FLAGS_SLEEP); intr_req->intr_attributes = USB_ATTRS_AUTOCLEARING; mblk = intr_req->intr_data; bcopy(buffer, mblk->b_wptr, ep_descr->wMaxPacketSize); mblk->b_wptr += ep_descr->wMaxPacketSize; if ((rval = usb_pipe_intr_xfer(pipe, intr_req, USB_FLAGS_SLEEP)) != USB_SUCCESS) { cmn_err (CE_WARN, "%s%d: Error writing intr data.", ddi_driver_name(dip), ddi_get_instance(dip)); }
ATTRIBUTE TYPE ATTRIBUTE VALUE |
Architecture PCI-based systems |
Interface stability Evolving |