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:
parent
7e6e6b6766
commit
29bd7d7e9a
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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) &&
|
||||
|
@ -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);
|
||||
|
||||
};
|
||||
|
@ -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 */
|
||||
|
@ -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 !
|
||||
|
@ -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 */
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user