From owner-p4-projects@FreeBSD.ORG Tue Dec 25 21:09:57 2007 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 9219616A419; Tue, 25 Dec 2007 21:09:57 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0457216A417 for ; Tue, 25 Dec 2007 21:09:57 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id DC2F813C457 for ; Tue, 25 Dec 2007 21:09:56 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id lBPL9u5B056695 for ; Tue, 25 Dec 2007 21:09:56 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id lBPL9uxT056692 for perforce@freebsd.org; Tue, 25 Dec 2007 21:09:56 GMT (envelope-from hselasky@FreeBSD.org) Date: Tue, 25 Dec 2007 21:09:56 GMT Message-Id: <200712252109.lBPL9uxT056692@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 131619 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Dec 2007 21:09:57 -0000 http://perforce.freebsd.org/chv.cgi?CH=131619 Change 131619 by hselasky@hselasky_laptop001 on 2007/12/25 21:09:50 This commit adds the following to the "if_cdce" driver: o Interrupt endpoint support. o Full Device Side Mode support. o Debug prints. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/if_cdce.c#37 edit .. //depot/projects/usb/src/sys/dev/usb/if_cdcereg.h#14 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/if_cdce.c#37 (text+ko) ==== @@ -73,11 +73,15 @@ static device_attach_t cdce_attach; static device_detach_t cdce_detach; static device_shutdown_t cdce_shutdown; +static usb_handle_request_t cdce_handle_request; static usbd_callback_t cdce_bulk_write_clear_stall_callback; static usbd_callback_t cdce_bulk_write_callback; static usbd_callback_t cdce_bulk_read_clear_stall_callback; static usbd_callback_t cdce_bulk_read_callback; +static usbd_callback_t cdce_intr_read_clear_stall_callback; +static usbd_callback_t cdce_intr_read_callback; +static usbd_callback_t cdce_intr_write_callback; static void cdce_start_cb(struct ifnet *ifp); static void cdce_start_transfers(struct cdce_softc *sc); @@ -88,18 +92,37 @@ static int cdce_ifmedia_upd_cb(struct ifnet *ifp); static void cdce_ifmedia_sts_cb(struct ifnet *const ifp, struct ifmediareq *req); +#ifdef USB_DEBUG +#define DPRINTF(sc,n,fmt,...) \ + do { if (cdce_debug > (n)) { \ + printf("%s:%s: " fmt, (sc)->sc_name, \ + __FUNCTION__,## __VA_ARGS__); } } while (0) + +static int cdce_debug = 0; + +SYSCTL_NODE(_hw_usb, OID_AUTO, cdce, CTLFLAG_RW, 0, "USB cdce"); +SYSCTL_INT(_hw_usb_cdce, OID_AUTO, debug, CTLFLAG_RW, &cdce_debug, 0, + "cdce debug level"); +#else #define DPRINTF(...) +#endif -static const struct usbd_config cdce_config[CDCE_ENDPT_MAX] = { +static const struct usbd_config cdce_config[CDCE_N_TRANSFER] = { [0] = { .type = UE_BULK, .endpoint = UE_ADDR_ANY, .direction = UE_DIR_OUT, .bufsize = (MCLBYTES + 4), + .if_index = 0, + /* Host Mode */ .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,}, .mh.callback = &cdce_bulk_write_callback, .mh.timeout = 10000, /* 10 seconds */ + /* Device Mode */ + .md.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, + .md.callback = &cdce_bulk_read_callback, + .md.timeout = 0, /* no timeout */ }, [1] = { @@ -107,8 +130,15 @@ .endpoint = UE_ADDR_ANY, .direction = UE_DIR_IN, .bufsize = (MCLBYTES + 4), + .if_index = 0, + /* Host Mode */ .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, .mh.callback = &cdce_bulk_read_callback, + .mh.timeout = 0, /* no timeout */ + /* Device Mode */ + .md.flags = {.pipe_bof = 1,.force_short_xfer = 1,}, + .md.callback = &cdce_bulk_write_callback, + .md.timeout = 10000, /* 10 seconds */ }, [2] = { @@ -116,10 +146,12 @@ .endpoint = 0x00, /* Control pipe */ .direction = UE_DIR_ANY, .bufsize = sizeof(usb_device_request_t), + .interval = 50, /* 50ms */ + .if_index = 0, + /* Host Mode Only */ .mh.flags = {}, .mh.callback = &cdce_bulk_write_clear_stall_callback, .mh.timeout = 1000, /* 1 second */ - .interval = 50, /* 50ms */ }, [3] = { @@ -127,14 +159,48 @@ .endpoint = 0x00, /* Control pipe */ .direction = UE_DIR_ANY, .bufsize = sizeof(usb_device_request_t), + .interval = 50, /* 50ms */ + .if_index = 0, + /* Host Mode Only */ .mh.flags = {}, .mh.callback = &cdce_bulk_read_clear_stall_callback, .mh.timeout = 1000, /* 1 second */ + }, + + [4] = { + .type = UE_INTERRUPT, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_IN, + .bufsize = CDCE_IND_SIZE_MAX, + .if_index = 1, + /* Host Mode */ + .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,}, + .mh.callback = &cdce_intr_read_callback, + .mh.timeout = 0, + /* Device Mode */ + .md.flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,}, + .md.callback = &cdce_intr_write_callback, + .md.timeout = 10000, /* 10 seconds */ + }, + + [5] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .bufsize = sizeof(usb_device_request_t), .interval = 50, /* 50ms */ + .if_index = 1, + /* Host Mode Only */ + .mh.flags = {}, + .mh.callback = &cdce_intr_read_clear_stall_callback, + .mh.timeout = 1000, /* 1 second */ }, }; static device_method_t cdce_methods[] = { + /* USB interface */ + DEVMETHOD(usb_handle_request, cdce_handle_request), + /* Device interface */ DEVMETHOD(device_probe, cdce_probe), DEVMETHOD(device_attach, cdce_attach), @@ -181,9 +247,6 @@ struct usb_attach_arg *uaa = device_get_ivars(dev); usb_interface_descriptor_t *id; - if (uaa->usb_mode != USB_MODE_HOST) { - return (UMATCH_NONE); - } if (uaa->iface == NULL) { return (UMATCH_NONE); } @@ -237,7 +300,8 @@ mtx_init(&(sc->sc_mtx), "cdce lock", NULL, MTX_DEF | MTX_RECURSE); if (sc->sc_flags & CDCE_FLAG_NO_UNION) { - sc->sc_data_iface_index = uaa->iface_index; + sc->sc_ifaces_index[0] = uaa->iface_index; + sc->sc_ifaces_index[1] = uaa->iface_index; sc->sc_data_iface_no = 0; /* not used */ goto alloc_transfers; } @@ -261,7 +325,8 @@ if (id && (id->bInterfaceNumber == sc->sc_data_iface_no)) { - sc->sc_data_iface_index = i; + sc->sc_ifaces_index[0] = i; + sc->sc_ifaces_index[1] = uaa->iface_index; USBD_SET_IFACE_NO_PROBE(uaa->device, i); break; } @@ -295,7 +360,7 @@ for (i = 0; i < 32; i++) { error = usbd_set_alt_interface_index - (uaa->device, sc->sc_data_iface_index, i); + (uaa->device, sc->sc_ifaces_index[0], i); if (error) { device_printf(dev, "no valid alternate " @@ -303,8 +368,8 @@ goto detach; } error = usbd_transfer_setup - (uaa->device, &(sc->sc_data_iface_index), - sc->sc_xfer, cdce_config, CDCE_ENDPT_MAX, + (uaa->device, sc->sc_ifaces_index, + sc->sc_xfer, cdce_config, CDCE_N_TRANSFER, sc, &(sc->sc_mtx)); if (error == 0) { @@ -389,6 +454,11 @@ ether_ifattach(ifp, eaddr); + /* start the interrupt transfer, if any */ + mtx_lock(&(sc->sc_mtx)); + usbd_transfer_start(sc->sc_xfer[4]); + mtx_unlock(&(sc->sc_mtx)); + return (0); /* success */ detach: @@ -411,7 +481,7 @@ mtx_unlock(&(sc->sc_mtx)); /* stop all USB transfers first */ - usbd_transfer_unsetup(sc->sc_xfer, CDCE_ENDPT_MAX); + usbd_transfer_unsetup(sc->sc_xfer, CDCE_N_TRANSFER); /* get rid of any late children */ bus_generic_detach(dev); @@ -463,7 +533,6 @@ if (usbd_clear_stall_callback(xfer, xfer_other)) { DPRINTF(sc, 0, "stall cleared\n"); - sc->sc_flags &= ~CDCE_FLAG_WRITE_STALL; usbd_transfer_start(xfer_other); } return; @@ -484,8 +553,9 @@ ifp->if_opackets++; case USBD_ST_SETUP: - - if (sc->sc_flags & CDCE_FLAG_WRITE_STALL) { +tr_setup: + if (xfer->flags.stall_pipe && + (xfer->flags_int.usb_mode == USB_MODE_HOST)) { usbd_transfer_start(sc->sc_xfer[2]); goto done; } @@ -531,8 +601,8 @@ if (xfer->error != USBD_CANCELLED) { /* try to clear stall first */ - sc->sc_flags |= CDCE_FLAG_WRITE_STALL; - usbd_transfer_start(sc->sc_xfer[2]); + xfer->flags.stall_pipe = 1; + goto tr_setup; } ifp->if_oerrors++; return; @@ -653,11 +723,16 @@ ifp->if_drv_flags |= IFF_DRV_RUNNING; - sc->sc_flags |= (CDCE_FLAG_READ_STALL | - CDCE_FLAG_WRITE_STALL | + sc->sc_flags |= ( CDCE_FLAG_LL_READY | CDCE_FLAG_HL_READY); + if (sc->sc_xfer[0]) { + sc->sc_xfer[0]->flags.stall_pipe = 1; + } + if (sc->sc_xfer[1]) { + sc->sc_xfer[1]->flags.stall_pipe = 1; + } cdce_start_transfers(sc); mtx_unlock(&(sc->sc_mtx)); @@ -673,7 +748,6 @@ if (usbd_clear_stall_callback(xfer, xfer_other)) { DPRINTF(sc, 0, "stall cleared\n"); - sc->sc_flags &= ~CDCE_FLAG_READ_STALL; usbd_transfer_start(xfer_other); } return; @@ -716,8 +790,8 @@ case USBD_ST_SETUP: tr_setup: - - if (sc->sc_flags & CDCE_FLAG_READ_STALL) { + if (xfer->flags.stall_pipe && + (xfer->flags_int.usb_mode == USB_MODE_HOST)) { usbd_transfer_start(sc->sc_xfer[3]); } else { xfer->frlengths[0] = xfer->max_data_length; @@ -739,8 +813,8 @@ default: /* Error */ if (xfer->error != USBD_CANCELLED) { /* try to clear stall first */ - sc->sc_flags |= CDCE_FLAG_READ_STALL; - usbd_transfer_start(sc->sc_xfer[3]); + xfer->flags.stall_pipe = 1; + goto tr_setup; } DPRINTF(sc, 0, "bulk read error, %s\n", usbd_errstr(xfer->error)); @@ -752,7 +826,6 @@ static int cdce_ifmedia_upd_cb(struct ifnet *ifp) { - /* no-op, cdce has only 1 possible media type */ return (0); } @@ -764,3 +837,97 @@ req->ifm_status = IFM_AVALID | IFM_ACTIVE; req->ifm_active = IFM_ETHER | IFM_10_T; } + +static void +cdce_intr_read_clear_stall_callback(struct usbd_xfer *xfer) +{ + struct cdce_softc *sc = xfer->priv_sc; + struct usbd_xfer *xfer_other = sc->sc_xfer[4]; + + if (usbd_clear_stall_callback(xfer, xfer_other)) { + DPRINTF(sc, 0, "stall cleared\n"); + usbd_transfer_start(xfer_other); + } + return; +} + +static void +cdce_intr_read_callback(struct usbd_xfer *xfer) +{ + struct cdce_softc *sc = xfer->priv_sc; + + switch (USBD_GET_STATE(xfer)) { + case USBD_ST_TRANSFERRED: + + DPRINTF(sc, 0, "Received %d bytes\n", + xfer->actlen); + + /* TODO: decode some indications */ + + case USBD_ST_SETUP: +tr_setup: + if (xfer->flags.stall_pipe && + (xfer->flags_int.usb_mode == USB_MODE_HOST)) { + usbd_transfer_start(sc->sc_xfer[5]); + } else { + xfer->frlengths[0] = xfer->max_data_length; + usbd_start_hardware(xfer); + } + break; + + default: /* Error */ + if (xfer->error != USBD_CANCELLED) { + /* start clear stall */ + xfer->flags.stall_pipe = 1; + goto tr_setup; + } + break; + } + return; +} + +static void +cdce_intr_write_callback(struct usbd_xfer *xfer) +{ + struct cdce_softc *sc = xfer->priv_sc; + + switch (USBD_GET_STATE(xfer)) { + case USBD_ST_TRANSFERRED: + + DPRINTF(sc, 0, "Transferred %d bytes\n", xfer->actlen); + + case USBD_ST_SETUP: +tr_setup: + if (xfer->flags.stall_pipe && + (xfer->flags_int.usb_mode == USB_MODE_HOST)) { + usbd_transfer_start(sc->sc_xfer[5]); + } else { +#if 0 + xfer->frlengths[0] = XXX; + usbd_start_hardware(xfer); +#endif + } + break; + + default: /* Error */ + if (xfer->error != USBD_CANCELLED) { + /* start clear stall */ + xfer->flags.stall_pipe = 1; + goto tr_setup; + } + break; + } + return; +} + +static int +cdce_handle_request(device_t dev, const void *req, void **pptr, + uint16_t *plen, uint16_t offset, uint8_t is_complete) +{ +#ifdef USB_DEBUG + struct cdce_softc *sc = device_get_softc(dev); + + DPRINTF(sc, 0, "\n"); +#endif + return (ENXIO); /* use builtin handling */ +} ==== //depot/projects/usb/src/sys/dev/usb/if_cdcereg.h#14 (text+ko) ==== @@ -35,7 +35,8 @@ #ifndef _USB_IF_CDCEREG_H_ #define _USB_IF_CDCEREG_H_ -#define CDCE_ENDPT_MAX 4 +#define CDCE_N_TRANSFER 6 +#define CDCE_IND_SIZE_MAX 32 /* bytes */ struct cdce_type { struct usb_devno cdce_dev; @@ -49,7 +50,7 @@ struct mtx sc_mtx; struct ifnet *sc_ifp; - struct usbd_xfer *sc_xfer[CDCE_ENDPT_MAX]; + struct usbd_xfer *sc_xfer[CDCE_N_TRANSFER]; struct usbd_device *sc_udev; device_t sc_dev; @@ -60,12 +61,10 @@ #define CDCE_FLAG_NO_UNION 0x0002 #define CDCE_FLAG_LL_READY 0x0004 #define CDCE_FLAG_HL_READY 0x0008 -#define CDCE_FLAG_WRITE_STALL 0x0010 -#define CDCE_FLAG_READ_STALL 0x0020 uint8_t sc_name[16]; uint8_t sc_data_iface_no; - uint8_t sc_data_iface_index; + uint8_t sc_ifaces_index[2]; }; #endif /* _USB_IF_CDCEREG_H_ */