Author: hselasky
Date: Sat Mar 22 17:20:10 2014
New Revision: 263644
URL: http://svnweb.freebsd.org/changeset/base/263644

Log:
  MFC r263159:
  Workaround for USB MIDI adapters which use non-supported values of
  wMaxPacketSize for BULK endpoints.

Modified:
  stable/9/sys/dev/sound/usb/uaudio.c
  stable/9/sys/dev/usb/usb_core.h
  stable/9/sys/dev/usb/usb_transfer.c
  stable/9/sys/dev/usb/usbdi.h
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/dev/   (props changed)

Modified: stable/9/sys/dev/sound/usb/uaudio.c
==============================================================================
--- stable/9/sys/dev/sound/usb/uaudio.c Sat Mar 22 17:18:44 2014        
(r263643)
+++ stable/9/sys/dev/sound/usb/uaudio.c Sat Mar 22 17:20:10 2014        
(r263644)
@@ -5674,6 +5674,25 @@ umidi_probe(device_t dev)
                DPRINTF("error=%s\n", usbd_errstr(error));
                goto detach;
        }
+
+       /*
+        * Some USB MIDI device makers couldn't resist using
+        * wMaxPacketSize = 4 for RX and TX BULK endpoints, although
+        * that size is an unsupported value for FULL speed BULK
+        * endpoints. The same applies to some HIGH speed MIDI devices
+        * which are using a wMaxPacketSize different from 512 bytes.
+        *
+        * Refer to section 5.8.3 in USB 2.0 PDF: Cite: "All Host
+        * Controllers are required to have support for 8-, 16-, 32-,
+        * and 64-byte maximum packet sizes for full-speed bulk
+        * endpoints and 512 bytes for high-speed bulk endpoints."
+        */
+       if (usbd_xfer_maxp_was_clamped(chan->xfer[UMIDI_TX_TRANSFER]))
+               chan->single_command = 1;
+
+       if (chan->single_command != 0)
+               device_printf(dev, "Single command MIDI quirk enabled\n");
+
        if ((chan->max_cable > UMIDI_CABLES_MAX) ||
            (chan->max_cable == 0)) {
                chan->max_cable = UMIDI_CABLES_MAX;

Modified: stable/9/sys/dev/usb/usb_core.h
==============================================================================
--- stable/9/sys/dev/usb/usb_core.h     Sat Mar 22 17:18:44 2014        
(r263643)
+++ stable/9/sys/dev/usb/usb_core.h     Sat Mar 22 17:20:10 2014        
(r263644)
@@ -113,6 +113,8 @@ struct usb_xfer_flags_int {
        uint8_t can_cancel_immed:1;     /* set if USB transfer can be
                                         * cancelled immediately */
        uint8_t doing_callback:1;       /* set if executing the callback */
+       uint8_t maxp_was_clamped:1;     /* set if the max packet size 
+                                        * was outside its allowed range */
 };
 
 /*

Modified: stable/9/sys/dev/usb/usb_transfer.c
==============================================================================
--- stable/9/sys/dev/usb/usb_transfer.c Sat Mar 22 17:18:44 2014        
(r263643)
+++ stable/9/sys/dev/usb/usb_transfer.c Sat Mar 22 17:20:10 2014        
(r263644)
@@ -322,6 +322,7 @@ usbd_transfer_setup_sub(struct usb_setup
        usb_frcount_t n_frlengths;
        usb_frcount_t n_frbuffers;
        usb_frcount_t x;
+       uint16_t maxp_old;
        uint8_t type;
        uint8_t zmps;
 
@@ -407,6 +408,11 @@ usbd_transfer_setup_sub(struct usb_setup
        if (xfer->max_packet_count > parm->hc_max_packet_count) {
                xfer->max_packet_count = parm->hc_max_packet_count;
        }
+
+       /* store max packet size value before filtering */
+
+       maxp_old = xfer->max_packet_size;
+
        /* filter "wMaxPacketSize" according to HC capabilities */
 
        if ((xfer->max_packet_size > parm->hc_max_packet_size) ||
@@ -439,6 +445,13 @@ usbd_transfer_setup_sub(struct usb_setup
                }
        }
 
+       /*
+        * Check if the max packet size was outside its allowed range
+        * and clamped to a valid value:
+        */
+       if (maxp_old != xfer->max_packet_size)
+               xfer->flags_int.maxp_was_clamped = 1;
+       
        /* compute "max_frame_size" */
 
        usbd_update_max_frame_size(xfer);
@@ -3365,3 +3378,13 @@ usbd_xfer_get_timestamp(struct usb_xfer 
 {
        return (xfer->isoc_time_complete);
 }
+
+/*
+ * The following function returns non-zero if the max packet size
+ * field was clamped to a valid value. Else it returns zero.
+ */
+uint8_t
+usbd_xfer_maxp_was_clamped(struct usb_xfer *xfer)
+{
+       return (xfer->flags_int.maxp_was_clamped);
+}

Modified: stable/9/sys/dev/usb/usbdi.h
==============================================================================
--- stable/9/sys/dev/usb/usbdi.h        Sat Mar 22 17:18:44 2014        
(r263643)
+++ stable/9/sys/dev/usb/usbdi.h        Sat Mar 22 17:20:10 2014        
(r263644)
@@ -549,6 +549,7 @@ int usbd_xfer_is_stalled(struct usb_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);
+uint8_t usbd_xfer_maxp_was_clamped(struct usb_xfer *xfer);
 
 void   usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
            const void *ptr, usb_frlength_t len);
_______________________________________________
svn-src-stable-9@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-stable-9
To unsubscribe, send any mail to "svn-src-stable-9-unsubscr...@freebsd.org"

Reply via email to