summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/usb/usb_transfer.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/dev/usb/usb_transfer.c')
-rw-r--r--freebsd/sys/dev/usb/usb_transfer.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/freebsd/sys/dev/usb/usb_transfer.c b/freebsd/sys/dev/usb/usb_transfer.c
index 7ea25337..2478d937 100644
--- a/freebsd/sys/dev/usb/usb_transfer.c
+++ b/freebsd/sys/dev/usb/usb_transfer.c
@@ -111,6 +111,33 @@ static const struct usb_config usb_control_ep_cfg[USB_CTRL_XFER_MAX] = {
},
};
+static const struct usb_config usb_control_ep_quirk_cfg[USB_CTRL_XFER_MAX] = {
+
+ /* This transfer is used for generic control endpoint transfers */
+
+ [0] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control endpoint */
+ .direction = UE_DIR_ANY,
+ .bufsize = 65535, /* bytes */
+ .callback = &usb_request_callback,
+ .usb_mode = USB_MODE_DUAL, /* both modes */
+ },
+
+ /* This transfer is used for generic clear stall only */
+
+ [1] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = UE_DIR_ANY,
+ .bufsize = sizeof(struct usb_device_request),
+ .callback = &usb_do_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ .interval = 50, /* 50ms */
+ .usb_mode = USB_MODE_HOST,
+ },
+};
+
/* function prototypes */
static void usbd_update_max_frame_size(struct usb_xfer *);
@@ -1051,7 +1078,8 @@ usbd_transfer_setup(struct usb_device *udev,
* context, else there is a chance of
* deadlock!
*/
- if (setup_start == usb_control_ep_cfg)
+ if (setup_start == usb_control_ep_cfg ||
+ setup_start == usb_control_ep_quirk_cfg)
info->done_p =
USB_BUS_CONTROL_XFER_PROC(udev->bus);
else if (xfer_mtx == &Giant)
@@ -2595,11 +2623,14 @@ usbd_transfer_done(struct usb_xfer *xfer, usb_error_t error)
}
#endif
/* keep some statistics */
- if (xfer->error) {
- info->bus->stats_err.uds_requests
+ if (xfer->error == USB_ERR_CANCELLED) {
+ info->udev->stats_cancelled.uds_requests
+ [xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++;
+ } else if (xfer->error != USB_ERR_NORMAL_COMPLETION) {
+ info->udev->stats_err.uds_requests
[xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++;
} else {
- info->bus->stats_ok.uds_requests
+ info->udev->stats_ok.uds_requests
[xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++;
}
@@ -3179,7 +3210,8 @@ repeat:
*/
iface_index = 0;
if (usbd_transfer_setup(udev, &iface_index,
- udev->ctrl_xfer, usb_control_ep_cfg, USB_CTRL_XFER_MAX, NULL,
+ udev->ctrl_xfer, udev->bus->control_ep_quirk ?
+ usb_control_ep_quirk_cfg : usb_control_ep_cfg, USB_CTRL_XFER_MAX, NULL,
&udev->device_mtx)) {
DPRINTFN(0, "could not setup default "
"USB transfer\n");