svn commit: r277298 - head/sys/dev/usb/net

Ruslan Bukin br at FreeBSD.org
Sat Jan 17 12:31:28 UTC 2015


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)


More information about the svn-src-all mailing list