Sync to p4

- Add support for devices that handle set and clear stall in hardware.
 - Add missing get timestamp function
 - Add more xfer flags

Submitted by:	Hans Petter Selasky
Approved by:	re (kib)
This commit is contained in:
thompsa 2009-06-27 21:23:30 +00:00
parent 6a523f03ea
commit ff880be8b9
13 changed files with 82 additions and 23 deletions

View File

@ -1227,7 +1227,7 @@ at91dci_device_done(struct usb_xfer *xfer, usb_error_t error)
static void
at91dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
struct usb_endpoint *ep)
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct at91dci_softc *sc;
uint32_t csr_val;

View File

@ -1113,7 +1113,7 @@ atmegadci_device_done(struct usb_xfer *xfer, usb_error_t error)
static void
atmegadci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
struct usb_endpoint *ep)
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct atmegadci_softc *sc;
uint8_t ep_no;

View File

@ -1081,7 +1081,7 @@ avr32dci_device_done(struct usb_xfer *xfer, usb_error_t error)
static void
avr32dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
struct usb_endpoint *ep)
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct avr32dci_softc *sc;
uint8_t ep_no;

View File

@ -1473,7 +1473,7 @@ musbotg_device_done(struct usb_xfer *xfer, usb_error_t error)
static void
musbotg_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
struct usb_endpoint *ep)
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct musbotg_softc *sc;
uint8_t ep_no;

View File

@ -1202,7 +1202,7 @@ uss820dci_device_done(struct usb_xfer *xfer, usb_error_t error)
static void
uss820dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
struct usb_endpoint *ep)
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct uss820dci_softc *sc;
uint8_t ep_no;

View File

@ -764,7 +764,7 @@ cdce_intr_write_callback(struct usb_xfer *xfer, usb_error_t error)
static int
cdce_handle_request(device_t dev,
const void *req, void **pptr, uint16_t *plen,
uint16_t offset, uint8_t is_complete)
uint16_t offset, uint8_t *pstate)
{
return (ENXIO); /* use builtin handler */
}

View File

@ -475,10 +475,11 @@ ustorage_fs_transfer_stop(struct ustorage_fs_softc *sc)
static int
ustorage_fs_handle_request(device_t dev,
const void *preq, void **pptr, uint16_t *plen,
uint16_t offset, uint8_t is_complete)
uint16_t offset, uint8_t *pstate)
{
struct ustorage_fs_softc *sc = device_get_softc(dev);
const struct usb_device_request *req = preq;
uint8_t is_complete = *pstate;
if (!is_complete) {
if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&

View File

@ -96,7 +96,7 @@ struct usb_bus_methods {
/* USB Device mode only - Mandatory */
void (*get_hw_ep_profile) (struct usb_device *udev, const struct usb_hw_ep_profile **ppf, uint8_t ep_addr);
void (*set_stall) (struct usb_device *udev, struct usb_xfer *xfer, struct usb_endpoint *ep);
void (*set_stall) (struct usb_device *udev, struct usb_xfer *xfer, struct usb_endpoint *ep, uint8_t *did_stall);
void (*clear_stall) (struct usb_device *udev, struct usb_endpoint *ep);
};

View File

@ -936,7 +936,7 @@ usbd_set_endpoint_stall(struct usb_device *udev, struct usb_endpoint *ep,
* complete the USB transfer like in case of a timeout
* setting the error code "USB_ERR_STALLED".
*/
(udev->bus->methods->set_stall) (udev, xfer, ep);
(udev->bus->methods->set_stall) (udev, xfer, ep, &do_stall);
}
if (!do_stall) {
ep->toggle_next = 0; /* reset data toggle */

View File

@ -198,6 +198,7 @@ usb_handle_iface_request(struct usb_xfer *xfer,
struct usb_device *udev = xfer->xroot->udev;
int error;
uint8_t iface_index;
uint8_t temp_state;
if ((req.bmRequestType & 0x1F) == UT_INTERFACE) {
iface_index = req.wIndex[0]; /* unicast */
@ -222,6 +223,10 @@ usb_handle_iface_request(struct usb_xfer *xfer,
/* end of interfaces non-existing interface */
goto tr_stalled;
}
/* set initial state */
temp_state = state;
/* forward request to interface, if any */
if ((error != 0) &&
@ -233,7 +238,7 @@ usb_handle_iface_request(struct usb_xfer *xfer,
#endif
error = USB_HANDLE_REQUEST(iface->subdev,
&req, ppdata, plen,
off, state);
off, &temp_state);
}
iface_parent = usbd_get_iface(udev, iface->parent_iface_index);
@ -252,14 +257,18 @@ usb_handle_iface_request(struct usb_xfer *xfer,
(iface_parent->subdev != iface->subdev) &&
device_is_attached(iface_parent->subdev)) {
error = USB_HANDLE_REQUEST(iface_parent->subdev,
&req, ppdata, plen, off,
state);
&req, ppdata, plen, off, &temp_state);
}
if (error == 0) {
/* negativly adjust pointer and length */
*ppdata = ((uint8_t *)(*ppdata)) - off;
*plen += off;
goto tr_valid;
if ((state == USB_HR_NOT_COMPLETE) &&
(temp_state == USB_HR_COMPLETE_OK))
goto tr_short;
else
goto tr_valid;
} else if (error == ENOTTY) {
goto tr_stalled;
}
@ -337,6 +346,12 @@ usb_handle_iface_request(struct usb_xfer *xfer,
USB_XFER_LOCK(xfer);
return (0);
tr_short:
mtx_unlock(&Giant);
sx_unlock(udev->default_sx + 1);
USB_XFER_LOCK(xfer);
return (USB_ERR_SHORT_XFER);
tr_stalled:
mtx_unlock(&Giant);
sx_unlock(udev->default_sx + 1);
@ -444,6 +459,7 @@ usb_handle_request(struct usb_xfer *xfer)
uint16_t wValue;
uint16_t wIndex;
uint8_t state;
uint8_t is_complete = 1;
usb_error_t err;
union {
uWord wStatus;
@ -596,6 +612,9 @@ usb_handle_request(struct usb_xfer *xfer)
USB_ADD_BYTES(&src_zcopy, 0),
&max_len, req, off, state);
if (err == 0) {
is_complete = 0;
goto tr_valid;
} else if (err == USB_ERR_SHORT_XFER) {
goto tr_valid;
}
/*
@ -735,7 +754,7 @@ usb_handle_request(struct usb_xfer *xfer)
if (rem > xfer->max_data_length) {
rem = usbd_xfer_max_len(xfer);
}
if (rem != max_len) {
if ((rem != max_len) && (is_complete != 0)) {
/*
* If we don't transfer the data we can transfer, then
* the transfer is short !

View File

@ -36,6 +36,11 @@ INTERFACE usb;
# The device received a control request
#
# The value pointed to by "pstate" can be updated to
# "USB_HR_COMPLETE_OK" to indicate that the control
# read transfer is complete, in case of short USB
# control transfers.
#
# Return values:
# 0: Success
# ENOTTY: Transaction stalled
@ -47,5 +52,5 @@ METHOD int handle_request {
void **pptr; /* data pointer */
uint16_t *plen; /* maximum transfer length */
uint16_t offset; /* data offset */
uint8_t is_complete; /* set if transfer is complete, see USB_HR_XXX */
uint8_t *pstate; /* set if transfer is complete, see USB_HR_XXX */
};

View File

@ -2352,29 +2352,37 @@ usbd_pipe_start(struct usb_xfer_queue *pq)
(type == UE_INTERRUPT)) {
struct usb_device *udev;
struct usb_xfer_root *info;
uint8_t did_stall;
info = xfer->xroot;
udev = info->udev;
ep->is_stalled = 1;
did_stall = 1;
if (udev->flags.usb_mode == USB_MODE_DEVICE) {
(udev->bus->methods->set_stall) (
udev, NULL, ep);
udev, NULL, ep, &did_stall);
} else if (udev->default_xfer[1]) {
info = udev->default_xfer[1]->xroot;
if (usb_proc_msignal(
usb_proc_msignal(
&info->bus->non_giant_callback_proc,
&udev->cs_msg[0], &udev->cs_msg[1])) {
/* ignore */
}
&udev->cs_msg[0], &udev->cs_msg[1]);
} else {
/* should not happen */
DPRINTFN(0, "No stall handler!\n");
}
/*
* We get started again when the stall is cleared!
* Check if we should stall. Some USB hardware
* handles set- and clear-stall in hardware.
*/
return;
if (did_stall) {
/*
* The transfer will be continued when
* the clear-stall control endpoint
* message is received.
*/
ep->is_stalled = 1;
return;
}
}
}
/* Set or clear stall complete - special case */
@ -2966,6 +2974,12 @@ usbd_xfer_set_flag(struct usb_xfer *xfer, int flag)
case USB_SHORT_XFER_OK:
xfer->flags.short_xfer_ok = 1;
break;
case USB_MULTI_SHORT_OK:
xfer->flags.short_frames_ok = 1;
break;
case USB_MANUAL_STATUS:
xfer->flags.manual_status = 1;
break;
}
}
@ -2979,5 +2993,22 @@ usbd_xfer_clr_flag(struct usb_xfer *xfer, int flag)
case USB_SHORT_XFER_OK:
xfer->flags.short_xfer_ok = 0;
break;
case USB_MULTI_SHORT_OK:
xfer->flags.short_frames_ok = 0;
break;
case USB_MANUAL_STATUS:
xfer->flags.manual_status = 0;
break;
}
}
/*
* The following function returns in milliseconds when the isochronous
* transfer was completed by the hardware. The returned value wraps
* around 65536 milliseconds.
*/
uint16_t
usbd_xfer_get_timestamp(struct usb_xfer *xfer)
{
return (xfer->isoc_time_complete);
}

View File

@ -78,6 +78,8 @@ typedef enum { /* keep in sync with usb_errstr_table */
#define USB_SHORT_XFER_OK 0x0004 /* allow short reads */
#define USB_DELAY_STATUS_STAGE 0x0010 /* insert delay before STATUS stage */
#define USB_USER_DATA_PTR 0x0020 /* internal flag */
#define USB_MULTI_SHORT_OK 0x0040 /* allow multiple short frames */
#define USB_MANUAL_STATUS 0x0080 /* manual ctrl status */
#define USB_NO_TIMEOUT 0
#define USB_DEFAULT_TIMEOUT 5000 /* 5000 ms = 5 seconds */
@ -486,6 +488,7 @@ void usbd_xfer_set_stall(struct usb_xfer *xfer);
int usbd_xfer_is_stalled(struct usb_xfer *xfer);
void usbd_xfer_set_flag(struct usb_xfer *xfer, int flag);
void usbd_xfer_clr_flag(struct usb_xfer *xfer, int flag);
uint16_t usbd_xfer_get_timestamp(struct usb_xfer *xfer);
void usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
const void *ptr, usb_frlength_t len);