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@
This commit is contained in:
parent
240f3ae6d2
commit
c13d70380d
@ -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 @@ cdce_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
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 *xfer, usb_error_t error)
|
||||
/* 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 */
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user