diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/usb/controller/at91dci.c | 14 | ||||
-rw-r--r-- | sys/dev/usb/controller/atmegadci.c | 13 | ||||
-rw-r--r-- | sys/dev/usb/controller/avr32dci.c | 13 | ||||
-rw-r--r-- | sys/dev/usb/controller/dwc_otg.c | 13 | ||||
-rw-r--r-- | sys/dev/usb/controller/musb_otg.c | 13 | ||||
-rw-r--r-- | sys/dev/usb/controller/uss820dci.c | 13 | ||||
-rw-r--r-- | sys/dev/usb/controller/xhci.c | 123 | ||||
-rw-r--r-- | sys/dev/usb/controller/xhci.h | 19 | ||||
-rw-r--r-- | sys/dev/usb/usb.h | 20 | ||||
-rw-r--r-- | sys/dev/usb/usb_controller.h | 7 | ||||
-rw-r--r-- | sys/dev/usb/usb_core.h | 1 | ||||
-rw-r--r-- | sys/dev/usb/usb_debug.c | 6 | ||||
-rw-r--r-- | sys/dev/usb/usb_device.c | 87 | ||||
-rw-r--r-- | sys/dev/usb/usb_freebsd.h | 2 | ||||
-rw-r--r-- | sys/dev/usb/usb_generic.c | 6 | ||||
-rw-r--r-- | sys/dev/usb/usb_hub.c | 8 | ||||
-rw-r--r-- | sys/dev/usb/usb_ioctl.h | 6 | ||||
-rw-r--r-- | sys/dev/usb/usb_request.c | 9 | ||||
-rw-r--r-- | sys/dev/usb/usb_transfer.c | 43 | ||||
-rw-r--r-- | sys/dev/usb/usbdi.h | 12 | ||||
-rw-r--r-- | sys/sys/param.h | 2 |
21 files changed, 326 insertions, 104 deletions
diff --git a/sys/dev/usb/controller/at91dci.c b/sys/dev/usb/controller/at91dci.c index e7d5e6e..d8fdc63 100644 --- a/sys/dev/usb/controller/at91dci.c +++ b/sys/dev/usb/controller/at91dci.c @@ -1226,7 +1226,14 @@ at91dci_device_done(struct usb_xfer *xfer, usb_error_t error) } static void -at91dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer, +at91dci_xfer_stall(struct usb_xfer *xfer) +{ + USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED); + at91dci_device_done(xfer, USB_ERR_STALLED); +} + +static void +at91dci_set_stall(struct usb_device *udev, struct usb_endpoint *ep, uint8_t *did_stall) { struct at91dci_softc *sc; @@ -1237,10 +1244,6 @@ at91dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer, DPRINTFN(5, "endpoint=%p\n", ep); - if (xfer) { - /* cancel any ongoing transfers */ - at91dci_device_done(xfer, USB_ERR_STALLED); - } /* set FORCESTALL */ sc = AT9100_DCI_BUS2SC(udev->bus); csr_reg = (ep->edesc->bEndpointAddress & UE_ADDR); @@ -2332,6 +2335,7 @@ struct usb_bus_methods at91dci_bus_methods = .xfer_unsetup = &at91dci_xfer_unsetup, .get_hw_ep_profile = &at91dci_get_hw_ep_profile, .set_stall = &at91dci_set_stall, + .xfer_stall = &at91dci_xfer_stall, .clear_stall = &at91dci_clear_stall, .roothub_exec = &at91dci_roothub_exec, .xfer_poll = &at91dci_do_poll, diff --git a/sys/dev/usb/controller/atmegadci.c b/sys/dev/usb/controller/atmegadci.c index 700ca8f..d8f9111 100644 --- a/sys/dev/usb/controller/atmegadci.c +++ b/sys/dev/usb/controller/atmegadci.c @@ -1113,7 +1113,13 @@ atmegadci_device_done(struct usb_xfer *xfer, usb_error_t error) } static void -atmegadci_set_stall(struct usb_device *udev, struct usb_xfer *xfer, +atmegadci_xfer_stall(struct usb_xfer *xfer) +{ + atmegadci_device_done(xfer, USB_ERR_STALLED); +} + +static void +atmegadci_set_stall(struct usb_device *udev, struct usb_endpoint *ep, uint8_t *did_stall) { struct atmegadci_softc *sc; @@ -1123,10 +1129,6 @@ atmegadci_set_stall(struct usb_device *udev, struct usb_xfer *xfer, DPRINTFN(5, "endpoint=%p\n", ep); - if (xfer) { - /* cancel any ongoing transfers */ - atmegadci_device_done(xfer, USB_ERR_STALLED); - } sc = ATMEGA_BUS2SC(udev->bus); /* get endpoint number */ ep_no = (ep->edesc->bEndpointAddress & UE_ADDR); @@ -2151,6 +2153,7 @@ struct usb_bus_methods atmegadci_bus_methods = .xfer_setup = &atmegadci_xfer_setup, .xfer_unsetup = &atmegadci_xfer_unsetup, .get_hw_ep_profile = &atmegadci_get_hw_ep_profile, + .xfer_stall = &atmegadci_xfer_stall, .set_stall = &atmegadci_set_stall, .clear_stall = &atmegadci_clear_stall, .roothub_exec = &atmegadci_roothub_exec, diff --git a/sys/dev/usb/controller/avr32dci.c b/sys/dev/usb/controller/avr32dci.c index 9f9cd5d..7a672f6 100644 --- a/sys/dev/usb/controller/avr32dci.c +++ b/sys/dev/usb/controller/avr32dci.c @@ -1080,7 +1080,13 @@ avr32dci_device_done(struct usb_xfer *xfer, usb_error_t error) } static void -avr32dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer, +avr32dci_xfer_stall(struct usb_xfer *xfer) +{ + avr32dci_device_done(xfer, USB_ERR_STALLED); +} + +static void +avr32dci_set_stall(struct usb_device *udev, struct usb_endpoint *pipe, uint8_t *did_stall) { struct avr32dci_softc *sc; @@ -1090,10 +1096,6 @@ avr32dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer, DPRINTFN(5, "pipe=%p\n", pipe); - if (xfer) { - /* cancel any ongoing transfers */ - avr32dci_device_done(xfer, USB_ERR_STALLED); - } sc = AVR32_BUS2SC(udev->bus); /* get endpoint number */ ep_no = (pipe->edesc->bEndpointAddress & UE_ADDR); @@ -2096,6 +2098,7 @@ struct usb_bus_methods avr32dci_bus_methods = .xfer_setup = &avr32dci_xfer_setup, .xfer_unsetup = &avr32dci_xfer_unsetup, .get_hw_ep_profile = &avr32dci_get_hw_ep_profile, + .xfer_stall = &avr32dci_xfer_stall, .set_stall = &avr32dci_set_stall, .clear_stall = &avr32dci_clear_stall, .roothub_exec = &avr32dci_roothub_exec, diff --git a/sys/dev/usb/controller/dwc_otg.c b/sys/dev/usb/controller/dwc_otg.c index f3ef19a..e5310f2 100644 --- a/sys/dev/usb/controller/dwc_otg.c +++ b/sys/dev/usb/controller/dwc_otg.c @@ -1524,7 +1524,13 @@ dwc_otg_device_done(struct usb_xfer *xfer, usb_error_t error) } static void -dwc_otg_set_stall(struct usb_device *udev, struct usb_xfer *xfer, +dwc_otg_xfer_stall(struct usb_xfer *xfer) +{ + dwc_otg_device_done(xfer, USB_ERR_STALLED); +} + +static void +dwc_otg_set_stall(struct usb_device *udev, struct usb_endpoint *ep, uint8_t *did_stall) { struct dwc_otg_softc *sc; @@ -1534,10 +1540,6 @@ dwc_otg_set_stall(struct usb_device *udev, struct usb_xfer *xfer, USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED); - if (xfer) { - /* cancel any ongoing transfers */ - dwc_otg_device_done(xfer, USB_ERR_STALLED); - } sc = DWC_OTG_BUS2SC(udev->bus); /* get endpoint address */ @@ -2625,6 +2627,7 @@ struct usb_bus_methods dwc_otg_bus_methods = .xfer_setup = &dwc_otg_xfer_setup, .xfer_unsetup = &dwc_otg_xfer_unsetup, .get_hw_ep_profile = &dwc_otg_get_hw_ep_profile, + .xfer_stall = &dwc_otg_xfer_stall, .set_stall = &dwc_otg_set_stall, .clear_stall = &dwc_otg_clear_stall, .roothub_exec = &dwc_otg_roothub_exec, diff --git a/sys/dev/usb/controller/musb_otg.c b/sys/dev/usb/controller/musb_otg.c index db0d54f..858cd0f 100644 --- a/sys/dev/usb/controller/musb_otg.c +++ b/sys/dev/usb/controller/musb_otg.c @@ -1472,7 +1472,13 @@ musbotg_device_done(struct usb_xfer *xfer, usb_error_t error) } static void -musbotg_set_stall(struct usb_device *udev, struct usb_xfer *xfer, +musbotg_xfer_stall(struct usb_xfer *xfer) +{ + musbotg_device_done(xfer, USB_ERR_STALLED); +} + +static void +musbotg_set_stall(struct usb_device *udev, struct usb_endpoint *ep, uint8_t *did_stall) { struct musbotg_softc *sc; @@ -1482,10 +1488,6 @@ musbotg_set_stall(struct usb_device *udev, struct usb_xfer *xfer, DPRINTFN(4, "endpoint=%p\n", ep); - if (xfer) { - /* cancel any ongoing transfers */ - musbotg_device_done(xfer, USB_ERR_STALLED); - } /* set FORCESTALL */ sc = MUSBOTG_BUS2SC(udev->bus); @@ -2801,6 +2803,7 @@ struct usb_bus_methods musbotg_bus_methods = .xfer_setup = &musbotg_xfer_setup, .xfer_unsetup = &musbotg_xfer_unsetup, .get_hw_ep_profile = &musbotg_get_hw_ep_profile, + .xfer_stall = &musbotg_xfer_stall, .set_stall = &musbotg_set_stall, .clear_stall = &musbotg_clear_stall, .roothub_exec = &musbotg_roothub_exec, diff --git a/sys/dev/usb/controller/uss820dci.c b/sys/dev/usb/controller/uss820dci.c index 19229f8..5bd479d 100644 --- a/sys/dev/usb/controller/uss820dci.c +++ b/sys/dev/usb/controller/uss820dci.c @@ -1210,7 +1210,13 @@ uss820dci_device_done(struct usb_xfer *xfer, usb_error_t error) } static void -uss820dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer, +uss820dci_xfer_stall(struct usb_xfer *xfer) +{ + uss820dci_device_done(xfer, USB_ERR_STALLED); +} + +static void +uss820dci_set_stall(struct usb_device *udev, struct usb_endpoint *ep, uint8_t *did_stall) { struct uss820dci_softc *sc; @@ -1223,10 +1229,6 @@ uss820dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer, DPRINTFN(5, "endpoint=%p\n", ep); - if (xfer) { - /* cancel any ongoing transfers */ - uss820dci_device_done(xfer, USB_ERR_STALLED); - } /* set FORCESTALL */ sc = USS820_DCI_BUS2SC(udev->bus); ep_no = (ep->edesc->bEndpointAddress & UE_ADDR); @@ -2385,6 +2387,7 @@ struct usb_bus_methods uss820dci_bus_methods = .xfer_setup = &uss820dci_xfer_setup, .xfer_unsetup = &uss820dci_xfer_unsetup, .get_hw_ep_profile = &uss820dci_get_hw_ep_profile, + .xfer_stall = &uss820dci_xfer_stall, .set_stall = &uss820dci_set_stall, .clear_stall = &uss820dci_clear_stall, .roothub_exec = &uss820dci_roothub_exec, diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c index 1a4e432..a20d7fa 100644 --- a/sys/dev/usb/controller/xhci.c +++ b/sys/dev/usb/controller/xhci.c @@ -128,7 +128,7 @@ static usb_proc_callback_t xhci_configure_msg; static usb_error_t xhci_configure_device(struct usb_device *); static usb_error_t xhci_configure_endpoint(struct usb_device *, struct usb_endpoint_descriptor *, uint64_t, uint16_t, - uint8_t, uint8_t, uint8_t, uint16_t, uint16_t); + uint8_t, uint8_t, uint8_t, uint16_t, uint16_t, uint8_t); static usb_error_t xhci_configure_mask(struct usb_device *, uint32_t, uint8_t); static usb_error_t xhci_cmd_evaluate_ctx(struct xhci_softc *, @@ -1245,7 +1245,7 @@ xhci_set_address(struct usb_device *udev, struct mtx *mtx, uint16_t address) &udev->ctrl_ep_desc); err = xhci_configure_endpoint(udev, &udev->ctrl_ep_desc, pepext->physaddr, - 0, 1, 1, 0, mps, mps); + 0, 1, 1, 0, mps, mps, USB_EP_MODE_DEFAULT); if (err != 0) { DPRINTF("Could not configure default endpoint\n"); @@ -1800,7 +1800,8 @@ xhci_setup_generic_chain(struct usb_xfer *xfer) /* compute multiplier for ISOCHRONOUS transfers */ mult = xfer->endpoint->ecomp ? - (xfer->endpoint->ecomp->bmAttributes & 3) : 0; + UE_GET_SS_ISO_MULT(xfer->endpoint->ecomp->bmAttributes) + : 0; /* check for USB 2.0 multiplier */ if (mult == 0) { mult = (xfer->endpoint->edesc-> @@ -2055,7 +2056,8 @@ static usb_error_t xhci_configure_endpoint(struct usb_device *udev, struct usb_endpoint_descriptor *edesc, uint64_t ring_addr, uint16_t interval, uint8_t max_packet_count, uint8_t mult, - uint8_t fps_shift, uint16_t max_packet_size, uint16_t max_frame_size) + uint8_t fps_shift, uint16_t max_packet_size, + uint16_t max_frame_size, uint8_t ep_mode) { struct usb_page_search buf_inp; struct xhci_softc *sc = XHCI_BUS2SC(udev->bus); @@ -2090,9 +2092,20 @@ xhci_configure_endpoint(struct usb_device *udev, if (mult == 0) return (USB_ERR_BAD_BUFSIZE); - temp = XHCI_EPCTX_0_EPSTATE_SET(0) | - XHCI_EPCTX_0_MAXP_STREAMS_SET(0) | - XHCI_EPCTX_0_LSA_SET(0); + if (ep_mode == USB_EP_MODE_STREAMS) { + temp = XHCI_EPCTX_0_EPSTATE_SET(0) | + XHCI_EPCTX_0_MAXP_STREAMS_SET(XHCI_MAX_STREAMS_LOG - 1) | + XHCI_EPCTX_0_LSA_SET(1); + + ring_addr += sizeof(struct xhci_trb) * + XHCI_MAX_TRANSFERS * XHCI_MAX_STREAMS; + } else { + temp = XHCI_EPCTX_0_EPSTATE_SET(0) | + XHCI_EPCTX_0_MAXP_STREAMS_SET(0) | + XHCI_EPCTX_0_LSA_SET(0); + + ring_addr |= XHCI_EPCTX_2_DCS_SET(1); + } switch (udev->speed) { case USB_SPEED_FULL: @@ -2160,9 +2173,6 @@ xhci_configure_endpoint(struct usb_device *udev, temp |= XHCI_EPCTX_1_EPTYPE_SET(4); xhci_ctx_set_le32(sc, &pinp->ctx_ep[epno - 1].dwEpCtx1, temp); - - ring_addr |= XHCI_EPCTX_2_DCS_SET(1); - xhci_ctx_set_le64(sc, &pinp->ctx_ep[epno - 1].qwEpCtx2, ring_addr); switch (edesc->bmAttributes & UE_XFERTYPE) { @@ -2195,21 +2205,42 @@ xhci_configure_endpoint_by_xfer(struct usb_xfer *xfer) { struct xhci_endpoint_ext *pepext; struct usb_endpoint_ss_comp_descriptor *ecomp; + usb_stream_t x; pepext = xhci_get_endpoint_ext(xfer->xroot->udev, xfer->endpoint->edesc); ecomp = xfer->endpoint->ecomp; - pepext->trb[0].dwTrb3 = 0; /* halt any transfers */ + for (x = 0; x != XHCI_MAX_STREAMS; x++) { + uint64_t temp; + + /* halt any transfers */ + pepext->trb[x * XHCI_MAX_TRANSFERS].dwTrb3 = 0; + + /* compute start of TRB ring for stream "x" */ + temp = pepext->physaddr + + (x * XHCI_MAX_TRANSFERS * sizeof(struct xhci_trb)) + + XHCI_SCTX_0_SCT_SEC_TR_RING; + + /* make tree structure */ + pepext->trb[(XHCI_MAX_TRANSFERS * + XHCI_MAX_STREAMS) + x].qwTrb0 = htole64(temp); + + /* reserved fields */ + pepext->trb[(XHCI_MAX_TRANSFERS * + XHCI_MAX_STREAMS) + x].dwTrb2 = 0; + pepext->trb[(XHCI_MAX_TRANSFERS * + XHCI_MAX_STREAMS) + x].dwTrb3 = 0; + } usb_pc_cpu_flush(pepext->page_cache); return (xhci_configure_endpoint(xfer->xroot->udev, xfer->endpoint->edesc, pepext->physaddr, xfer->interval, xfer->max_packet_count, - (ecomp != NULL) ? (ecomp->bmAttributes & 3) + 1 : 1, + (ecomp != NULL) ? UE_GET_SS_ISO_MULT(ecomp->bmAttributes) + 1 : 1, usbd_xfer_get_fps_shift(xfer), xfer->max_packet_size, - xfer->max_frame_size)); + xfer->max_frame_size, xfer->endpoint->ep_mode)); } static usb_error_t @@ -2500,7 +2531,8 @@ xhci_get_endpoint_ext(struct usb_device *udev, struct usb_endpoint_descriptor *e pc = &sc->sc_hw.devs[index].endpoint_pc; - usbd_get_page(pc, (uintptr_t)&((struct xhci_dev_endpoint_trbs *)0)->trb[epno][0], &buf_ep); + usbd_get_page(pc, (uintptr_t)&((struct xhci_dev_endpoint_trbs *)0)-> + trb[epno][0], &buf_ep); pepext = &sc->sc_hw.devs[index].endp[epno]; pepext->page_cache = pc; @@ -2539,7 +2571,7 @@ xhci_transfer_remove(struct usb_xfer *xfer, usb_error_t error) pepext = xhci_get_endpoint_ext(xfer->xroot->udev, xfer->endpoint->edesc); - pepext->trb_used--; + pepext->trb_used[xfer->stream_id]--; pepext->xfer[xfer->qh_pos] = NULL; @@ -2557,12 +2589,15 @@ xhci_transfer_insert(struct usb_xfer *xfer) struct xhci_td *td_last; struct xhci_endpoint_ext *pepext; uint64_t addr; + usb_stream_t id; uint8_t i; uint8_t inext; uint8_t trb_limit; DPRINTFN(8, "\n"); + id = xfer->stream_id; + /* check if already inserted */ if (xfer->flags_int.bandwidth_reclaimed) { DPRINTFN(8, "Already in schedule\n"); @@ -2588,7 +2623,7 @@ xhci_transfer_insert(struct usb_xfer *xfer) break; } - if (pepext->trb_used >= trb_limit) { + if (pepext->trb_used[id] >= trb_limit) { DPRINTFN(8, "Too many TDs queued.\n"); return (USB_ERR_NOMEM); } @@ -2605,10 +2640,10 @@ xhci_transfer_insert(struct usb_xfer *xfer) return (0); } - pepext->trb_used++; + pepext->trb_used[id]++; /* get current TRB index */ - i = pepext->trb_index; + i = pepext->trb_index[id]; /* get next TRB index */ inext = (i + 1); @@ -2617,8 +2652,12 @@ xhci_transfer_insert(struct usb_xfer *xfer) if (inext >= (XHCI_MAX_TRANSFERS - 1)) inext = 0; + /* offset for stream */ + i += id * XHCI_MAX_TRANSFERS; + inext += id * XHCI_MAX_TRANSFERS; + /* compute terminating return address */ - addr += inext * sizeof(struct xhci_trb); + addr += (inext * sizeof(struct xhci_trb)); /* update next pointer of last link TRB */ td_last->td_trb[td_last->ntrb].qwTrb0 = htole64(addr); @@ -2662,7 +2701,7 @@ xhci_transfer_insert(struct usb_xfer *xfer) xfer->flags_int.bandwidth_reclaimed = 1; - pepext->trb_index = inext; + pepext->trb_index[id] = inext; xhci_endpoint_doorbell(xfer); @@ -2750,12 +2789,12 @@ xhci_device_generic_close(struct usb_xfer *xfer) static void xhci_device_generic_multi_enter(struct usb_endpoint *ep, - struct usb_xfer *enter_xfer) + usb_stream_t stream_id, struct usb_xfer *enter_xfer) { struct usb_xfer *xfer; /* check if there is a current transfer */ - xfer = ep->endpoint_q.curr; + xfer = ep->endpoint_q[stream_id].curr; if (xfer == NULL) return; @@ -2767,7 +2806,7 @@ xhci_device_generic_multi_enter(struct usb_endpoint *ep, if (!xfer->flags_int.bandwidth_reclaimed) return; - xfer = TAILQ_FIRST(&ep->endpoint_q.head); + xfer = TAILQ_FIRST(&ep->endpoint_q[stream_id].head); if (xfer == NULL) { /* * In case of enter we have to consider that the @@ -2792,7 +2831,8 @@ xhci_device_generic_enter(struct usb_xfer *xfer) /* setup TD's and QH */ xhci_setup_generic_chain(xfer); - xhci_device_generic_multi_enter(xfer->endpoint, xfer); + xhci_device_generic_multi_enter(xfer->endpoint, + xfer->stream_id, xfer); } static void @@ -2804,7 +2844,8 @@ xhci_device_generic_start(struct usb_xfer *xfer) xhci_transfer_insert(xfer); /* try to multi buffer */ - xhci_device_generic_multi_enter(xfer->endpoint, NULL); + xhci_device_generic_multi_enter(xfer->endpoint, + xfer->stream_id, NULL); /* add transfer last on interrupt queue */ usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer); @@ -3465,6 +3506,7 @@ xhci_configure_reset_endpoint(struct usb_xfer *xfer) struct usb_endpoint_descriptor *edesc; struct usb_page_cache *pcinp; usb_error_t err; + usb_stream_t stream_id; uint8_t index; uint8_t epno; @@ -3481,6 +3523,7 @@ xhci_configure_reset_endpoint(struct usb_xfer *xfer) edesc = xfer->endpoint->edesc; epno = edesc->bEndpointAddress; + stream_id = xfer->stream_id; if ((edesc->bmAttributes & UE_XFERTYPE) == UE_CONTROL) epno |= UE_DIR_IN; @@ -3516,8 +3559,10 @@ xhci_configure_reset_endpoint(struct usb_xfer *xfer) if (err != 0) DPRINTF("Could not reset endpoint %u\n", epno); - err = xhci_cmd_set_tr_dequeue_ptr(sc, pepext->physaddr | - XHCI_EPCTX_2_DCS_SET(1), 0, epno, index); + err = xhci_cmd_set_tr_dequeue_ptr(sc, + (pepext->physaddr + (stream_id * sizeof(struct xhci_trb) * + XHCI_MAX_TRANSFERS)) | XHCI_EPCTX_2_DCS_SET(1), + stream_id, epno, index); if (err != 0) DPRINTF("Could not set dequeue ptr for endpoint %u\n", epno); @@ -3615,7 +3660,8 @@ restart: /* check if halted is still cleared */ if (pepext->trb_halted == 0) { pepext->trb_running = 1; - pepext->trb_index = 0; + memset(pepext->trb_index, 0, + sizeof(pepext->trb_index)); } goto restart; } @@ -3639,7 +3685,8 @@ restart: xhci_transfer_insert(xfer); /* try to multi buffer */ - xhci_device_generic_multi_enter(xfer->endpoint, NULL); + xhci_device_generic_multi_enter(xfer->endpoint, + xfer->stream_id, NULL); } } @@ -3946,6 +3993,23 @@ xhci_device_state_change(struct usb_device *udev) XHCI_CMD_UNLOCK(sc); } +static usb_error_t +xhci_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep, + uint8_t ep_mode) +{ + switch (ep_mode) { + case USB_EP_MODE_DEFAULT: + return (0); + case USB_EP_MODE_STREAMS: + if ((ep->edesc->bmAttributes & UE_XFERTYPE) != UE_BULK || + udev->speed != USB_SPEED_SUPER) + return (USB_ERR_INVAL); + return (0); + default: + return (USB_ERR_INVAL); + } +} + struct usb_bus_methods xhci_bus_methods = { .endpoint_init = xhci_ep_init, .endpoint_uninit = xhci_ep_uninit, @@ -3964,4 +4028,5 @@ struct usb_bus_methods xhci_bus_methods = { .clear_stall = xhci_ep_clear_stall, .device_state_change = xhci_device_state_change, .set_hw_power_sleep = xhci_set_hw_power_sleep, + .set_endpoint_mode = xhci_set_endpoint_mode, }; diff --git a/sys/dev/usb/controller/xhci.h b/sys/dev/usb/controller/xhci.h index 14afcaf..f6d467f 100644 --- a/sys/dev/usb/controller/xhci.h +++ b/sys/dev/usb/controller/xhci.h @@ -35,7 +35,15 @@ #define XHCI_MAX_COMMANDS (16 * 1) #define XHCI_MAX_RSEG 1 #define XHCI_MAX_TRANSFERS 4 - +#if USB_MAX_EP_STREAMS == 8 +#define XHCI_MAX_STREAMS 8 +#define XHCI_MAX_STREAMS_LOG 3 +#elif USB_MAX_EP_STREAMS == 1 +#define XHCI_MAX_STREAMS 1 +#define XHCI_MAX_STREAMS_LOG 0 +#else +#error "The USB_MAX_EP_STREAMS value is not supported." +#endif #define XHCI_DEV_CTX_ADDR_ALIGN 64 /* bytes */ #define XHCI_DEV_CTX_ALIGN 64 /* bytes */ #define XHCI_INPUT_CTX_ALIGN 64 /* bytes */ @@ -307,7 +315,8 @@ struct xhci_trb { } __aligned(4); struct xhci_dev_endpoint_trbs { - struct xhci_trb trb[XHCI_MAX_ENDPOINTS][XHCI_MAX_TRANSFERS]; + struct xhci_trb trb[XHCI_MAX_ENDPOINTS] + [(XHCI_MAX_STREAMS * XHCI_MAX_TRANSFERS) + XHCI_MAX_STREAMS]; }; #define XHCI_TD_PAGE_NBUF 17 /* units, room enough for 64Kbytes */ @@ -353,11 +362,11 @@ struct xhci_hw_root { struct xhci_endpoint_ext { struct xhci_trb *trb; - struct usb_xfer *xfer[XHCI_MAX_TRANSFERS - 1]; + struct usb_xfer *xfer[XHCI_MAX_TRANSFERS * XHCI_MAX_STREAMS]; struct usb_page_cache *page_cache; uint64_t physaddr; - uint8_t trb_used; - uint8_t trb_index; + uint8_t trb_used[XHCI_MAX_STREAMS]; + uint8_t trb_index[XHCI_MAX_STREAMS]; uint8_t trb_halted; uint8_t trb_running; }; diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h index 38ddc2d..e6fb5e5 100644 --- a/sys/dev/usb/usb.h +++ b/sys/dev/usb/usb.h @@ -546,6 +546,8 @@ struct usb_endpoint_ss_comp_descriptor { uByte bDescriptorType; uByte bMaxBurst; uByte bmAttributes; +#define UE_GET_BULK_STREAMS(x) ((x) & 0x0F) +#define UE_GET_SS_ISO_MULT(x) ((x) & 0x03) uWord wBytesPerInterval; } __packed; typedef struct usb_endpoint_ss_comp_descriptor @@ -744,7 +746,7 @@ enum usb_revision { #define USB_REV_MAX (USB_REV_3_0+1) /* - * Supported host contoller modes. + * Supported host controller modes. */ enum usb_hc_mode { USB_MODE_HOST, /* initiates transfers */ @@ -754,7 +756,7 @@ enum usb_hc_mode { #define USB_MODE_MAX (USB_MODE_DUAL+1) /* - * The "USB_MODE" macros defines all the supported device states. + * The "USB_STATE" enums define all the supported device states. */ enum usb_dev_state { USB_STATE_DETACHED, @@ -764,4 +766,18 @@ enum usb_dev_state { USB_STATE_CONFIGURED, }; #define USB_STATE_MAX (USB_STATE_CONFIGURED+1) + +/* + * The "USB_EP_MODE" macros define all the currently supported + * endpoint modes. + */ +enum usb_ep_mode { + USB_EP_MODE_DEFAULT, + USB_EP_MODE_STREAMS, /* USB3.0 specific */ + USB_EP_MODE_HW_MASS_STORAGE, + USB_EP_MODE_HW_SERIAL, + USB_EP_MODE_HW_ETHERNET_CDC, + USB_EP_MODE_HW_ETHERNET_NCM, + USB_EP_MODE_MAX +}; #endif /* _USB_STANDARD_H_ */ diff --git a/sys/dev/usb/usb_controller.h b/sys/dev/usb/usb_controller.h index bbbf66b..6c14454 100644 --- a/sys/dev/usb/usb_controller.h +++ b/sys/dev/usb/usb_controller.h @@ -108,7 +108,8 @@ struct usb_bus_methods { /* USB Device mode only - Mandatory */ void (*get_hw_ep_profile) (struct usb_device *udev, const struct usb_hw_ep_profile **ppf, uint8_t ep_addr); - void (*set_stall) (struct usb_device *udev, struct usb_xfer *xfer, struct usb_endpoint *ep, uint8_t *did_stall); + void (*xfer_stall) (struct usb_xfer *xfer); + void (*set_stall) (struct usb_device *udev, struct usb_endpoint *ep, uint8_t *did_stall); /* USB Device mode mandatory. USB Host mode optional. */ @@ -143,6 +144,10 @@ struct usb_bus_methods { /* Optional for host mode */ usb_error_t (*set_address) (struct usb_device *, struct mtx *, uint16_t); + + /* Optional for device and host mode */ + + usb_error_t (*set_endpoint_mode) (struct usb_device *, struct usb_endpoint *, uint8_t); }; /* diff --git a/sys/dev/usb/usb_core.h b/sys/dev/usb/usb_core.h index 3dfd0d1..776cf17 100644 --- a/sys/dev/usb/usb_core.h +++ b/sys/dev/usb/usb_core.h @@ -151,6 +151,7 @@ struct usb_xfer { usb_frcount_t nframes; /* number of USB frames to transfer */ usb_frcount_t aframes; /* actual number of USB frames * transferred */ + usb_stream_t stream_id; /* USB3.0 specific field */ uint16_t max_packet_size; uint16_t max_frame_size; diff --git a/sys/dev/usb/usb_debug.c b/sys/dev/usb/usb_debug.c index a39d400..ae0db7f 100644 --- a/sys/dev/usb/usb_debug.c +++ b/sys/dev/usb/usb_debug.c @@ -113,10 +113,12 @@ void usb_dump_queue(struct usb_endpoint *ep) { struct usb_xfer *xfer; + usb_stream_t x; printf("usb_dump_queue: endpoint=%p xfer: ", ep); - TAILQ_FOREACH(xfer, &ep->endpoint_q.head, wait_entry) { - printf(" %p", xfer); + for (x = 0; x != USB_MAX_EP_STREAMS; x++) { + TAILQ_FOREACH(xfer, &ep->endpoint_q[x].head, wait_entry) + printf(" %p", xfer); } printf("\n"); } diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index de5e7d7..407d2ea 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -355,7 +355,6 @@ usbd_interface_count(struct usb_device *udev, uint8_t *count) return (USB_ERR_NORMAL_COMPLETION); } - /*------------------------------------------------------------------------* * usb_init_endpoint * @@ -370,6 +369,7 @@ usb_init_endpoint(struct usb_device *udev, uint8_t iface_index, struct usb_endpoint *ep) { struct usb_bus_methods *methods; + usb_stream_t x; methods = udev->bus->methods; @@ -379,13 +379,26 @@ usb_init_endpoint(struct usb_device *udev, uint8_t iface_index, ep->edesc = edesc; ep->ecomp = ecomp; ep->iface_index = iface_index; - TAILQ_INIT(&ep->endpoint_q.head); - ep->endpoint_q.command = &usbd_pipe_start; + + /* setup USB stream queues */ + for (x = 0; x != USB_MAX_EP_STREAMS; x++) { + TAILQ_INIT(&ep->endpoint_q[x].head); + ep->endpoint_q[x].command = &usbd_pipe_start; + } /* the pipe is not supported by the hardware */ if (ep->methods == NULL) return; + /* check for SUPER-speed streams mode endpoint */ + if (udev->speed == USB_SPEED_SUPER && ecomp != NULL && + (edesc->bmAttributes & UE_XFERTYPE) == UE_BULK && + (UE_GET_BULK_STREAMS(ecomp->bmAttributes) != 0)) { + usbd_set_endpoint_mode(udev, ep, USB_EP_MODE_STREAMS); + } else { + usbd_set_endpoint_mode(udev, ep, USB_EP_MODE_DEFAULT); + } + /* clear stall, if any */ if (methods->clear_stall != NULL) { USB_BUS_LOCK(udev->bus); @@ -933,6 +946,7 @@ usbd_set_endpoint_stall(struct usb_device *udev, struct usb_endpoint *ep, uint8_t do_stall) { struct usb_xfer *xfer; + usb_stream_t x; uint8_t et; uint8_t was_stalled; @@ -975,18 +989,22 @@ usbd_set_endpoint_stall(struct usb_device *udev, struct usb_endpoint *ep, if (do_stall || (!was_stalled)) { if (!was_stalled) { - /* lookup the current USB transfer, if any */ - xfer = ep->endpoint_q.curr; - } else { - xfer = NULL; + for (x = 0; x != USB_MAX_EP_STREAMS; x++) { + /* lookup the current USB transfer, if any */ + xfer = ep->endpoint_q[x].curr; + if (xfer != NULL) { + /* + * The "xfer_stall" method + * will complete the USB + * transfer like in case of a + * timeout setting the error + * code "USB_ERR_STALLED". + */ + (udev->bus->methods->xfer_stall) (xfer); + } + } } - - /* - * If "xfer" is non-NULL the "set_stall" method will - * complete the USB transfer like in case of a timeout - * setting the error code "USB_ERR_STALLED". - */ - (udev->bus->methods->set_stall) (udev, xfer, ep, &do_stall); + (udev->bus->methods->set_stall) (udev, ep, &do_stall); } if (!do_stall) { ep->toggle_next = 0; /* reset data toggle */ @@ -994,8 +1012,11 @@ usbd_set_endpoint_stall(struct usb_device *udev, struct usb_endpoint *ep, (udev->bus->methods->clear_stall) (udev, ep); - /* start up the current or next transfer, if any */ - usb_command_wrapper(&ep->endpoint_q, ep->endpoint_q.curr); + /* start the current or next transfer, if any */ + for (x = 0; x != USB_MAX_EP_STREAMS; x++) { + usb_command_wrapper(&ep->endpoint_q[x], + ep->endpoint_q[x].curr); + } } USB_BUS_UNLOCK(udev->bus); return (0); @@ -2745,3 +2766,37 @@ usbd_add_dynamic_quirk(struct usb_device *udev, uint16_t quirk) } return (USB_ERR_NOMEM); } + +/* + * The following function is used to select the endpoint mode. It + * should not be called outside enumeration context. + */ + +usb_error_t +usbd_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep, + uint8_t ep_mode) +{ + usb_error_t error; + + sx_assert(&udev->enum_sx, SA_LOCKED); + + if (udev->bus->methods->set_endpoint_mode != NULL) { + error = (udev->bus->methods->set_endpoint_mode) ( + udev, ep, ep_mode); + } else if (ep_mode != USB_EP_MODE_DEFAULT) { + error = USB_ERR_INVAL; + } else { + error = 0; + } + + /* only set new mode regardless of error */ + ep->ep_mode = ep_mode; + + return (error); +} + +uint8_t +usbd_get_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep) +{ + return (ep->ep_mode); +} diff --git a/sys/dev/usb/usb_freebsd.h b/sys/dev/usb/usb_freebsd.h index 349e13e..42a54c5 100644 --- a/sys/dev/usb/usb_freebsd.h +++ b/sys/dev/usb/usb_freebsd.h @@ -60,6 +60,7 @@ #define USB_MAX_DEVICES 128 /* units */ #define USB_IFACE_MAX 32 /* units */ #define USB_FIFO_MAX 128 /* units */ +#define USB_MAX_EP_STREAMS 8 /* units */ #define USB_MAX_FS_ISOC_FRAMES_PER_XFER (120) /* units */ #define USB_MAX_HS_ISOC_FRAMES_PER_XFER (8*120) /* units */ @@ -76,5 +77,6 @@ typedef uint32_t usb_frcount_t; /* units */ typedef uint32_t usb_size_t; /* bytes */ typedef uint32_t usb_ticks_t; /* system defined */ typedef uint16_t usb_power_mask_t; /* see "USB_HW_POWER_XXX" */ +typedef uint16_t usb_stream_t; /* stream ID */ #endif /* _USB_FREEBSD_H_ */ diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c index 5f156b1..8da4119 100644 --- a/sys/dev/usb/usb_generic.c +++ b/sys/dev/usb/usb_generic.c @@ -253,6 +253,7 @@ ugen_open_pipe_write(struct usb_fifo *f) usb_config[0].type = ed->bmAttributes & UE_XFERTYPE; usb_config[0].endpoint = ed->bEndpointAddress & UE_ADDR; + usb_config[0].stream_id = 0; /* XXX support more stream ID's */ usb_config[0].direction = UE_DIR_TX; usb_config[0].interval = USB_DEFAULT_INTERVAL; usb_config[0].flags.proxy_buffer = 1; @@ -321,6 +322,7 @@ ugen_open_pipe_read(struct usb_fifo *f) usb_config[0].type = ed->bmAttributes & UE_XFERTYPE; usb_config[0].endpoint = ed->bEndpointAddress & UE_ADDR; + usb_config[0].stream_id = 0; /* XXX support more stream ID's */ usb_config[0].direction = UE_DIR_RX; usb_config[0].interval = USB_DEFAULT_INTERVAL; usb_config[0].flags.proxy_buffer = 1; @@ -1391,6 +1393,7 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags) struct usb_fs_start *pstart; struct usb_fs_stop *pstop; struct usb_fs_open *popen; + struct usb_fs_open_streams *popen_streams; struct usb_fs_close *pclose; struct usb_fs_clear_stall_sync *pstall; void *addr; @@ -1455,6 +1458,7 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags) break; case USB_FS_OPEN: + case USB_FS_OPEN_STREAMS: if (u.popen->ep_index >= f->fs_ep_max) { error = EINVAL; break; @@ -1506,6 +1510,8 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags) usb_config[0].frames = u.popen->max_frames; usb_config[0].bufsize = u.popen->max_bufsize; usb_config[0].usb_mode = USB_MODE_DUAL; /* both modes */ + if (cmd == USB_FS_OPEN_STREAMS) + usb_config[0].stream_id = u.popen_streams->stream_id; if (usb_config[0].type == UE_CONTROL) { if (f->udev->flags.usb_mode != USB_MODE_HOST) { diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c index 85448b9..2f3dbe5 100644 --- a/sys/dev/usb/usb_hub.c +++ b/sys/dev/usb/usb_hub.c @@ -1757,9 +1757,11 @@ usbd_fs_isoc_schedule_alloc_slot(struct usb_xfer *isoc_xfer, uint16_t isoc_time) data_len += len; } - /* check double buffered transfers */ - - TAILQ_FOREACH(pipe_xfer, &xfer->endpoint->endpoint_q.head, + /* + * Check double buffered transfers. Only stream ID + * equal to zero is valid here! + */ + TAILQ_FOREACH(pipe_xfer, &xfer->endpoint->endpoint_q[0].head, wait_entry) { /* skip self, if any */ diff --git a/sys/dev/usb/usb_ioctl.h b/sys/dev/usb/usb_ioctl.h index 9af6ee5..5e8dab7 100644 --- a/sys/dev/usb/usb_ioctl.h +++ b/sys/dev/usb/usb_ioctl.h @@ -206,6 +206,11 @@ struct usb_fs_open { uint8_t ep_no; /* bEndpointNumber */ }; +struct usb_fs_open_streams { + struct usb_fs_open fs_open; + uint16_t stream_id; +}; + struct usb_fs_close { uint8_t ep_index; }; @@ -302,6 +307,7 @@ struct usb_gen_quirk { #define USB_FS_OPEN _IOWR('U', 197, struct usb_fs_open) #define USB_FS_CLOSE _IOW ('U', 198, struct usb_fs_close) #define USB_FS_CLEAR_STALL_SYNC _IOW ('U', 199, struct usb_fs_clear_stall_sync) +#define USB_FS_OPEN_STREAMS _IOWR('U', 200, struct usb_fs_open_streams) /* USB quirk system interface */ #define USB_DEV_QUIRK_GET _IOWR('Q', 0, struct usb_gen_quirk) diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c index f601154..57bd968 100644 --- a/sys/dev/usb/usb_request.c +++ b/sys/dev/usb/usb_request.c @@ -228,6 +228,7 @@ usb_do_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error) struct usb_endpoint *ep; struct usb_endpoint *ep_end; struct usb_endpoint *ep_first; + usb_stream_t x; uint8_t to; udev = xfer->xroot->udev; @@ -255,9 +256,11 @@ tr_transferred: ep->is_stalled = 0; /* some hardware needs a callback to clear the data toggle */ usbd_clear_stall_locked(udev, ep); - /* start up the current or next transfer, if any */ - usb_command_wrapper(&ep->endpoint_q, - ep->endpoint_q.curr); + for (x = 0; x != USB_MAX_EP_STREAMS; x++) { + /* start the current or next transfer, if any */ + usb_command_wrapper(&ep->endpoint_q[x], + ep->endpoint_q[x].curr); + } } ep++; diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c index b799897..e4cb5fb 100644 --- a/sys/dev/usb/usb_transfer.c +++ b/sys/dev/usb/usb_transfer.c @@ -358,7 +358,8 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm) switch (type) { case UE_ISOCHRONOUS: case UE_INTERRUPT: - xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3; + xfer->max_packet_count += + (xfer->max_packet_size >> 11) & 3; /* check for invalid max packet count */ if (xfer->max_packet_count > 3) @@ -387,7 +388,8 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm) if (ecomp != NULL) { uint8_t mult; - mult = (ecomp->bmAttributes & 3) + 1; + mult = UE_GET_SS_ISO_MULT( + ecomp->bmAttributes) + 1; if (mult > 3) mult = 3; @@ -946,7 +948,20 @@ usbd_transfer_setup(struct usb_device *udev, ep = usbd_get_endpoint(udev, ifaces[setup->if_index], setup); - if ((ep == NULL) || (ep->methods == NULL)) { + /* + * Check that the USB PIPE is valid and that + * the endpoint mode is proper. + * + * Make sure we don't allocate a streams + * transfer when such a combination is not + * valid. + */ + if ((ep == NULL) || (ep->methods == NULL) || + ((ep->ep_mode != USB_EP_MODE_STREAMS) && + (ep->ep_mode != USB_EP_MODE_DEFAULT)) || + (setup->stream_id != 0 && + (setup->stream_id >= USB_MAX_EP_STREAMS || + (ep->ep_mode != USB_EP_MODE_STREAMS)))) { if (setup->flags.no_pipe_ok) continue; if ((setup->usb_mode != USB_MODE_DUAL) && @@ -990,6 +1005,9 @@ usbd_transfer_setup(struct usb_device *udev, /* set transfer endpoint pointer */ xfer->endpoint = ep; + /* set transfer stream ID */ + xfer->stream_id = setup->stream_id; + parm.size[0] += sizeof(xfer[0]); parm.methods = xfer->endpoint->methods; parm.curr_xfer = xfer; @@ -1575,7 +1593,8 @@ usbd_transfer_submit(struct usb_xfer *xfer) USB_BUS_LOCK(bus); xfer->flags_int.can_cancel_immed = 1; /* start the transfer */ - usb_command_wrapper(&xfer->endpoint->endpoint_q, xfer); + usb_command_wrapper(&xfer->endpoint-> + endpoint_q[xfer->stream_id], xfer); USB_BUS_UNLOCK(bus); return; } @@ -1696,7 +1715,7 @@ usbd_pipe_enter(struct usb_xfer *xfer) } /* start the transfer */ - usb_command_wrapper(&ep->endpoint_q, xfer); + usb_command_wrapper(&ep->endpoint_q[xfer->stream_id], xfer); USB_BUS_UNLOCK(xfer->xroot->bus); } @@ -1817,8 +1836,9 @@ usbd_transfer_stop(struct usb_xfer *xfer) * If the current USB transfer is completing we need * to start the next one: */ - if (ep->endpoint_q.curr == xfer) { - usb_command_wrapper(&ep->endpoint_q, NULL); + if (ep->endpoint_q[xfer->stream_id].curr == xfer) { + usb_command_wrapper( + &ep->endpoint_q[xfer->stream_id], NULL); } } @@ -2533,7 +2553,7 @@ usbd_pipe_start(struct usb_xfer_queue *pq) if (udev->flags.usb_mode == USB_MODE_DEVICE) { (udev->bus->methods->set_stall) ( - udev, NULL, ep, &did_stall); + udev, ep, &did_stall); } else if (udev->ctrl_xfer[1]) { info = udev->ctrl_xfer[1]->xroot; usb_proc_msignal( @@ -2800,10 +2820,11 @@ usbd_callback_wrapper_sub(struct usb_xfer *xfer) * next one: */ USB_BUS_LOCK(bus); - if (ep->endpoint_q.curr == xfer) { - usb_command_wrapper(&ep->endpoint_q, NULL); + if (ep->endpoint_q[xfer->stream_id].curr == xfer) { + usb_command_wrapper(&ep->endpoint_q[xfer->stream_id], NULL); - if (ep->endpoint_q.curr || TAILQ_FIRST(&ep->endpoint_q.head)) { + if (ep->endpoint_q[xfer->stream_id].curr != NULL || + TAILQ_FIRST(&ep->endpoint_q[xfer->stream_id].head) != NULL) { /* there is another USB transfer waiting */ } else { /* this is the last USB transfer */ diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index 653f395..4193118 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -133,7 +133,8 @@ struct usb_xfer_queue { * USB endpoint. */ struct usb_endpoint { - struct usb_xfer_queue endpoint_q; /* queue of USB transfers */ + /* queue of USB transfers */ + struct usb_xfer_queue endpoint_q[USB_MAX_EP_STREAMS]; struct usb_endpoint_descriptor *edesc; struct usb_endpoint_ss_comp_descriptor *ecomp; @@ -156,6 +157,10 @@ struct usb_endpoint { uint8_t usb_smask; /* USB start mask */ uint8_t usb_cmask; /* USB complete mask */ uint8_t usb_uframe; /* USB microframe */ + + /* USB endpoint mode, see USB_EP_MODE_XXX */ + + uint8_t ep_mode; }; /* @@ -220,6 +225,7 @@ struct usb_config { #define USB_DEFAULT_INTERVAL 0 usb_timeout_t timeout; /* transfer timeout in milliseconds */ struct usb_xfer_flags flags; /* transfer flags */ + usb_stream_t stream_id; /* USB3.0 specific */ enum usb_hc_mode usb_mode; /* host or device mode */ uint8_t type; /* pipe type */ uint8_t endpoint; /* pipe number */ @@ -477,6 +483,10 @@ usb_error_t usbd_set_pnpinfo(struct usb_device *udev, uint8_t iface_index, const char *pnpinfo); usb_error_t usbd_add_dynamic_quirk(struct usb_device *udev, uint16_t quirk); +usb_error_t usbd_set_endpoint_mode(struct usb_device *udev, + struct usb_endpoint *ep, uint8_t ep_mode); +uint8_t usbd_get_endpoint_mode(struct usb_device *udev, + struct usb_endpoint *ep); const struct usb_device_id *usbd_lookup_id_by_info( const struct usb_device_id *id, usb_size_t sizeof_id, diff --git a/sys/sys/param.h b/sys/sys/param.h index 80a24a8..a3bf897 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1000016 /* Master, propagated to newvers */ +#define __FreeBSD_version 1000017 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, |