svn commit: r190184 - head/sys/dev/usb
Andrew Thompson
thompsa at FreeBSD.org
Fri Mar 20 15:01:46 PDT 2009
Author: thompsa
Date: Fri Mar 20 22:01:45 2009
New Revision: 190184
URL: http://svn.freebsd.org/changeset/base/190184
Log:
MFp4 //depot/projects/usb @159479,159502,159516,159522,159529
Workaround for buggy USB hardware not handling new SETUP packet before STATUS
stage is complete, this allows xfers to endpoint0 to return a short frame.
Submitted by: Hans Petter Selasky
Reported by: me
Modified:
head/sys/dev/usb/usb_transfer.c
Modified: head/sys/dev/usb/usb_transfer.c
==============================================================================
--- head/sys/dev/usb/usb_transfer.c Fri Mar 20 21:57:54 2009 (r190183)
+++ head/sys/dev/usb/usb_transfer.c Fri Mar 20 22:01:45 2009 (r190184)
@@ -113,7 +113,6 @@ static const struct usb2_config usb2_con
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
.mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
.mh.callback = &usb2_do_clear_stall_callback,
.mh.timeout = 1000, /* 1 second */
.mh.interval = 50, /* 50ms */
@@ -1251,6 +1250,20 @@ usb2_start_hardware_sub(struct usb2_xfer
/* no longer active */
xfer->flags_int.control_act = 0;
}
+
+ /* Check for invalid number of frames */
+ if (xfer->nframes > 2) {
+ /*
+ * If you need to split a control transfer, you
+ * have to do one part at a time. Only with
+ * non-control transfers you can do multiple
+ * parts a time.
+ */
+ DPRINTFN(0, "Too many frames: %u\n",
+ (unsigned int)xfer->nframes);
+ goto error;
+ }
+
/*
* Check if there is a control
* transfer in progress:
@@ -1495,23 +1508,28 @@ usb2_start_hardware(struct usb2_xfer *xf
*/
if (USB_GET_DATA_ISREAD(xfer)) {
- if (xfer->flags_int.control_xfr) {
-
- /*
- * Control transfers do not support reception
- * of multiple short USB frames !
- */
+ if (xfer->flags.short_frames_ok) {
+ xfer->flags_int.short_xfer_ok = 1;
+ xfer->flags_int.short_frames_ok = 1;
+ } else if (xfer->flags.short_xfer_ok) {
+ xfer->flags_int.short_xfer_ok = 1;
- if (xfer->flags.short_xfer_ok) {
- xfer->flags_int.short_xfer_ok = 1;
- }
- } else {
-
- if (xfer->flags.short_frames_ok) {
- xfer->flags_int.short_xfer_ok = 1;
+ /* check for control transfer */
+ if (xfer->flags_int.control_xfr) {
+ /*
+ * 1) Control transfers do not support
+ * reception of multiple short USB
+ * frames in host mode and device side
+ * mode, with exception of:
+ *
+ * 2) Due to sometimes buggy device
+ * side firmware we need to do a
+ * STATUS stage in case of short
+ * control transfers in USB host mode.
+ * The STATUS stage then becomes the
+ * "alt_next" to the DATA stage.
+ */
xfer->flags_int.short_frames_ok = 1;
- } else if (xfer->flags.short_xfer_ok) {
- xfer->flags_int.short_xfer_ok = 1;
}
}
}
@@ -2652,7 +2670,6 @@ usb2_clear_data_toggle(struct usb2_devic
* .interval = 50, //50 milliseconds
* .bufsize = sizeof(struct usb2_device_request),
* .mh.timeout = 1000, //1.000 seconds
- * .mh.flags = { },
* .mh.callback = &my_clear_stall_callback, // **
* };
*
More information about the svn-src-all
mailing list