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