Author: br
Date: Sat Jan 17 12:31:26 2015
New Revision: 277298
URL: https://svnweb.freebsd.org/changeset/base/277298

Log:
  o Notify USB host about connection when operating in device mode.
    Required when communicating to Mac OS X USB host stack.
  o Also don't set stall bit to TX pipe in device mode as seems Mac OS X
    don't clears it as it should.
  
  Discussed with:       hselasky@

Modified:
  head/sys/dev/usb/net/if_cdce.c
  head/sys/dev/usb/net/if_cdcereg.h

Modified: head/sys/dev/usb/net/if_cdce.c
==============================================================================
--- head/sys/dev/usb/net/if_cdce.c      Sat Jan 17 11:43:13 2015        
(r277297)
+++ head/sys/dev/usb/net/if_cdce.c      Sat Jan 17 12:31:26 2015        
(r277298)
@@ -898,8 +898,14 @@ cdce_init(struct usb_ether *ue)
        usbd_transfer_start(sc->sc_xfer[CDCE_INTR_RX]);
        usbd_transfer_start(sc->sc_xfer[CDCE_INTR_TX]);
 
-       /* stall data write direction, which depends on USB mode */
-       usbd_xfer_set_stall(sc->sc_xfer[CDCE_BULK_TX]);
+       /*
+        * Stall data write direction, which depends on USB mode.
+        *
+        * Some USB host stacks (e.g. Mac OS X) don't clears stall
+        * bit as it should, so set it in our host mode only.
+        */
+       if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST)
+               usbd_xfer_set_stall(sc->sc_xfer[CDCE_BULK_TX]);
 
        /* start data transfers */
        cdce_start(ue);
@@ -1065,6 +1071,10 @@ tr_setup:
 static void
 cdce_intr_write_callback(struct usb_xfer *xfer, usb_error_t error)
 {
+       struct cdce_softc *sc = usbd_xfer_softc(xfer);
+       struct usb_cdc_notification req;
+       struct usb_page_cache *pc;
+       uint32_t speed;
        int actlen;
 
        usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
@@ -1077,10 +1087,50 @@ cdce_intr_write_callback(struct usb_xfer
                /* FALLTHROUGH */
        case USB_ST_SETUP:
 tr_setup:
-#if 0
-               usbd_xfer_set_frame_len(xfer, 0, XXX);
-               usbd_transfer_submit(xfer);
-#endif
+               /*
+                * Inform host about connection. Required according to USB CDC
+                * specification and communicating to Mac OS X USB host stack.
+                * Some of the values seems ignored by Mac OS X though.
+                */
+               if (sc->sc_notify_state == CDCE_NOTIFY_NETWORK_CONNECTION) {
+                       req.bmRequestType = UCDC_NOTIFICATION;
+                       req.bNotification = UCDC_N_NETWORK_CONNECTION;
+                       req.wIndex[0] = sc->sc_ifaces_index[1];
+                       req.wIndex[1] = 0;
+                       USETW(req.wValue, 1); /* Connected */
+                       USETW(req.wLength, 0);
+
+                       pc = usbd_xfer_get_frame(xfer, 0);
+                       usbd_copy_in(pc, 0, &req, sizeof(req));
+                       usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
+                       usbd_xfer_set_frames(xfer, 1);
+                       usbd_transfer_submit(xfer); 
+                       sc->sc_notify_state = CDCE_NOTIFY_SPEED_CHANGE;
+
+               } else if (sc->sc_notify_state == CDCE_NOTIFY_SPEED_CHANGE) {
+                       req.bmRequestType = UCDC_NOTIFICATION;
+                       req.bNotification = UCDC_N_CONNECTION_SPEED_CHANGE;
+                       req.wIndex[0] = sc->sc_ifaces_index[1];
+                       req.wIndex[1] = 0;
+                       USETW(req.wValue, 0);
+                       USETW(req.wLength, 8);
+
+                       /* Peak theoretical bulk trasfer rate in bits/s */
+                       if (usbd_get_speed(sc->sc_ue.ue_udev) == USB_SPEED_HIGH)
+                               speed = (13 * 512 * 8 * 1000 * 8);
+                       else
+                               speed = (19 * 64 * 1 * 1000 * 8);
+
+                       USETDW(req.data + 0, speed); /* Upstream bit rate */
+                       USETDW(req.data + 4, speed); /* Downstream bit rate */
+ 
+                       pc = usbd_xfer_get_frame(xfer, 0);
+                       usbd_copy_in(pc, 0, &req, sizeof(req));
+                       usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
+                       usbd_xfer_set_frames(xfer, 1);
+                       usbd_transfer_submit(xfer); 
+                       sc->sc_notify_state = CDCE_NOTIFY_DONE;
+               }
                break;
 
        default:                        /* Error */

Modified: head/sys/dev/usb/net/if_cdcereg.h
==============================================================================
--- head/sys/dev/usb/net/if_cdcereg.h   Sat Jan 17 11:43:13 2015        
(r277297)
+++ head/sys/dev/usb/net/if_cdcereg.h   Sat Jan 17 12:31:26 2015        
(r277298)
@@ -93,6 +93,10 @@ struct cdce_softc {
 
        uint8_t sc_eaddr_str_index;
        uint8_t sc_ifaces_index[2];
+       uint8_t sc_notify_state;
+#define        CDCE_NOTIFY_NETWORK_CONNECTION  0
+#define        CDCE_NOTIFY_SPEED_CHANGE        1
+#define        CDCE_NOTIFY_DONE                2
 };
 
 #define        CDCE_LOCK(_sc)                  mtx_lock(&(_sc)->sc_mtx)
_______________________________________________
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