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
|
static void
|
||||||
at91dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
|
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;
|
struct at91dci_softc *sc;
|
||||||
uint32_t csr_val;
|
uint32_t csr_val;
|
||||||
|
@ -1113,7 +1113,7 @@ atmegadci_device_done(struct usb_xfer *xfer, usb_error_t error)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
atmegadci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
|
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;
|
struct atmegadci_softc *sc;
|
||||||
uint8_t ep_no;
|
uint8_t ep_no;
|
||||||
|
@ -1081,7 +1081,7 @@ avr32dci_device_done(struct usb_xfer *xfer, usb_error_t error)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
avr32dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
|
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;
|
struct avr32dci_softc *sc;
|
||||||
uint8_t ep_no;
|
uint8_t ep_no;
|
||||||
|
@ -1473,7 +1473,7 @@ musbotg_device_done(struct usb_xfer *xfer, usb_error_t error)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
musbotg_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
|
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;
|
struct musbotg_softc *sc;
|
||||||
uint8_t ep_no;
|
uint8_t ep_no;
|
||||||
|
@ -1202,7 +1202,7 @@ uss820dci_device_done(struct usb_xfer *xfer, usb_error_t error)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
uss820dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
|
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;
|
struct uss820dci_softc *sc;
|
||||||
uint8_t ep_no;
|
uint8_t ep_no;
|
||||||
|
@ -764,7 +764,7 @@ cdce_intr_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||||||
static int
|
static int
|
||||||
cdce_handle_request(device_t dev,
|
cdce_handle_request(device_t dev,
|
||||||
const void *req, void **pptr, uint16_t *plen,
|
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 */
|
return (ENXIO); /* use builtin handler */
|
||||||
}
|
}
|
||||||
|
@ -475,10 +475,11 @@ ustorage_fs_transfer_stop(struct ustorage_fs_softc *sc)
|
|||||||
static int
|
static int
|
||||||
ustorage_fs_handle_request(device_t dev,
|
ustorage_fs_handle_request(device_t dev,
|
||||||
const void *preq, void **pptr, uint16_t *plen,
|
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);
|
struct ustorage_fs_softc *sc = device_get_softc(dev);
|
||||||
const struct usb_device_request *req = preq;
|
const struct usb_device_request *req = preq;
|
||||||
|
uint8_t is_complete = *pstate;
|
||||||
|
|
||||||
if (!is_complete) {
|
if (!is_complete) {
|
||||||
if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&
|
if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&
|
||||||
|
@ -96,7 +96,7 @@ struct usb_bus_methods {
|
|||||||
/* USB Device mode only - Mandatory */
|
/* 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 (*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);
|
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
|
* complete the USB transfer like in case of a timeout
|
||||||
* setting the error code "USB_ERR_STALLED".
|
* 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) {
|
if (!do_stall) {
|
||||||
ep->toggle_next = 0; /* reset data toggle */
|
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;
|
struct usb_device *udev = xfer->xroot->udev;
|
||||||
int error;
|
int error;
|
||||||
uint8_t iface_index;
|
uint8_t iface_index;
|
||||||
|
uint8_t temp_state;
|
||||||
|
|
||||||
if ((req.bmRequestType & 0x1F) == UT_INTERFACE) {
|
if ((req.bmRequestType & 0x1F) == UT_INTERFACE) {
|
||||||
iface_index = req.wIndex[0]; /* unicast */
|
iface_index = req.wIndex[0]; /* unicast */
|
||||||
@ -222,6 +223,10 @@ usb_handle_iface_request(struct usb_xfer *xfer,
|
|||||||
/* end of interfaces non-existing interface */
|
/* end of interfaces non-existing interface */
|
||||||
goto tr_stalled;
|
goto tr_stalled;
|
||||||
}
|
}
|
||||||
|
/* set initial state */
|
||||||
|
|
||||||
|
temp_state = state;
|
||||||
|
|
||||||
/* forward request to interface, if any */
|
/* forward request to interface, if any */
|
||||||
|
|
||||||
if ((error != 0) &&
|
if ((error != 0) &&
|
||||||
@ -233,7 +238,7 @@ usb_handle_iface_request(struct usb_xfer *xfer,
|
|||||||
#endif
|
#endif
|
||||||
error = USB_HANDLE_REQUEST(iface->subdev,
|
error = USB_HANDLE_REQUEST(iface->subdev,
|
||||||
&req, ppdata, plen,
|
&req, ppdata, plen,
|
||||||
off, state);
|
off, &temp_state);
|
||||||
}
|
}
|
||||||
iface_parent = usbd_get_iface(udev, iface->parent_iface_index);
|
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) &&
|
(iface_parent->subdev != iface->subdev) &&
|
||||||
device_is_attached(iface_parent->subdev)) {
|
device_is_attached(iface_parent->subdev)) {
|
||||||
error = USB_HANDLE_REQUEST(iface_parent->subdev,
|
error = USB_HANDLE_REQUEST(iface_parent->subdev,
|
||||||
&req, ppdata, plen, off,
|
&req, ppdata, plen, off, &temp_state);
|
||||||
state);
|
|
||||||
}
|
}
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
/* negativly adjust pointer and length */
|
/* negativly adjust pointer and length */
|
||||||
*ppdata = ((uint8_t *)(*ppdata)) - off;
|
*ppdata = ((uint8_t *)(*ppdata)) - off;
|
||||||
*plen += 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) {
|
} else if (error == ENOTTY) {
|
||||||
goto tr_stalled;
|
goto tr_stalled;
|
||||||
}
|
}
|
||||||
@ -337,6 +346,12 @@ usb_handle_iface_request(struct usb_xfer *xfer,
|
|||||||
USB_XFER_LOCK(xfer);
|
USB_XFER_LOCK(xfer);
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
tr_short:
|
||||||
|
mtx_unlock(&Giant);
|
||||||
|
sx_unlock(udev->default_sx + 1);
|
||||||
|
USB_XFER_LOCK(xfer);
|
||||||
|
return (USB_ERR_SHORT_XFER);
|
||||||
|
|
||||||
tr_stalled:
|
tr_stalled:
|
||||||
mtx_unlock(&Giant);
|
mtx_unlock(&Giant);
|
||||||
sx_unlock(udev->default_sx + 1);
|
sx_unlock(udev->default_sx + 1);
|
||||||
@ -444,6 +459,7 @@ usb_handle_request(struct usb_xfer *xfer)
|
|||||||
uint16_t wValue;
|
uint16_t wValue;
|
||||||
uint16_t wIndex;
|
uint16_t wIndex;
|
||||||
uint8_t state;
|
uint8_t state;
|
||||||
|
uint8_t is_complete = 1;
|
||||||
usb_error_t err;
|
usb_error_t err;
|
||||||
union {
|
union {
|
||||||
uWord wStatus;
|
uWord wStatus;
|
||||||
@ -596,6 +612,9 @@ usb_handle_request(struct usb_xfer *xfer)
|
|||||||
USB_ADD_BYTES(&src_zcopy, 0),
|
USB_ADD_BYTES(&src_zcopy, 0),
|
||||||
&max_len, req, off, state);
|
&max_len, req, off, state);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
|
is_complete = 0;
|
||||||
|
goto tr_valid;
|
||||||
|
} else if (err == USB_ERR_SHORT_XFER) {
|
||||||
goto tr_valid;
|
goto tr_valid;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -735,7 +754,7 @@ usb_handle_request(struct usb_xfer *xfer)
|
|||||||
if (rem > xfer->max_data_length) {
|
if (rem > xfer->max_data_length) {
|
||||||
rem = usbd_xfer_max_len(xfer);
|
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
|
* If we don't transfer the data we can transfer, then
|
||||||
* the transfer is short !
|
* the transfer is short !
|
||||||
|
@ -36,6 +36,11 @@ INTERFACE usb;
|
|||||||
|
|
||||||
# The device received a control request
|
# 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:
|
# Return values:
|
||||||
# 0: Success
|
# 0: Success
|
||||||
# ENOTTY: Transaction stalled
|
# ENOTTY: Transaction stalled
|
||||||
@ -47,5 +52,5 @@ METHOD int handle_request {
|
|||||||
void **pptr; /* data pointer */
|
void **pptr; /* data pointer */
|
||||||
uint16_t *plen; /* maximum transfer length */
|
uint16_t *plen; /* maximum transfer length */
|
||||||
uint16_t offset; /* data offset */
|
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)) {
|
(type == UE_INTERRUPT)) {
|
||||||
struct usb_device *udev;
|
struct usb_device *udev;
|
||||||
struct usb_xfer_root *info;
|
struct usb_xfer_root *info;
|
||||||
|
uint8_t did_stall;
|
||||||
|
|
||||||
info = xfer->xroot;
|
info = xfer->xroot;
|
||||||
udev = info->udev;
|
udev = info->udev;
|
||||||
ep->is_stalled = 1;
|
did_stall = 1;
|
||||||
|
|
||||||
if (udev->flags.usb_mode == USB_MODE_DEVICE) {
|
if (udev->flags.usb_mode == USB_MODE_DEVICE) {
|
||||||
(udev->bus->methods->set_stall) (
|
(udev->bus->methods->set_stall) (
|
||||||
udev, NULL, ep);
|
udev, NULL, ep, &did_stall);
|
||||||
} else if (udev->default_xfer[1]) {
|
} else if (udev->default_xfer[1]) {
|
||||||
info = udev->default_xfer[1]->xroot;
|
info = udev->default_xfer[1]->xroot;
|
||||||
if (usb_proc_msignal(
|
usb_proc_msignal(
|
||||||
&info->bus->non_giant_callback_proc,
|
&info->bus->non_giant_callback_proc,
|
||||||
&udev->cs_msg[0], &udev->cs_msg[1])) {
|
&udev->cs_msg[0], &udev->cs_msg[1]);
|
||||||
/* ignore */
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* should not happen */
|
/* should not happen */
|
||||||
DPRINTFN(0, "No stall handler!\n");
|
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 */
|
/* 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:
|
case USB_SHORT_XFER_OK:
|
||||||
xfer->flags.short_xfer_ok = 1;
|
xfer->flags.short_xfer_ok = 1;
|
||||||
break;
|
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:
|
case USB_SHORT_XFER_OK:
|
||||||
xfer->flags.short_xfer_ok = 0;
|
xfer->flags.short_xfer_ok = 0;
|
||||||
break;
|
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_SHORT_XFER_OK 0x0004 /* allow short reads */
|
||||||
#define USB_DELAY_STATUS_STAGE 0x0010 /* insert delay before STATUS stage */
|
#define USB_DELAY_STATUS_STAGE 0x0010 /* insert delay before STATUS stage */
|
||||||
#define USB_USER_DATA_PTR 0x0020 /* internal flag */
|
#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_NO_TIMEOUT 0
|
||||||
#define USB_DEFAULT_TIMEOUT 5000 /* 5000 ms = 5 seconds */
|
#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);
|
int usbd_xfer_is_stalled(struct usb_xfer *xfer);
|
||||||
void usbd_xfer_set_flag(struct usb_xfer *xfer, int flag);
|
void usbd_xfer_set_flag(struct usb_xfer *xfer, int flag);
|
||||||
void usbd_xfer_clr_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,
|
void usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
|
||||||
const void *ptr, usb_frlength_t len);
|
const void *ptr, usb_frlength_t len);
|
||||||
|
Loading…
Reference in New Issue
Block a user