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, // **
  * };
  *
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to