From: Kirill A. Korinsky Subject: sys/xhci: suppoort USB3 speeds To: OpenBSD tech Cc: Marcus Glocker Date: Thu, 27 Feb 2025 20:21:25 +0100 tech@, I'd like to add support of USB3 speeds to XHCI driver. This diff was tested on Snapdragon SoC: xhci0 at qcdwusb0, xHCI 1.10 usb0 at xhci0: USB revision 3.0 uhub0 at usb0 configuration 1 interface 0 "Generic xHCI root hub" rev 3.00/1.00 addr 1 I also used diff: https://marc.info/?l=openbsd-tech&m=174032299500347&w=2 and switched Elgato Facecam Pro to isochronous mode with streaming 3840x2160 30fps with 33740 isoc frames / packets. It works. Ok? Index: sys/dev/usb/usb_subr.c =================================================================== RCS file: /home/cvs/src/sys/dev/usb/usb_subr.c,v diff -u -p -r1.163 usb_subr.c --- sys/dev/usb/usb_subr.c 23 May 2024 03:21:09 -0000 1.163 +++ sys/dev/usb/usb_subr.c 27 Feb 2025 18:49:51 -0000 @@ -514,7 +514,8 @@ int usbd_parse_idesc(struct usbd_device *dev, struct usbd_interface *ifc) { #define ed ((usb_endpoint_descriptor_t *)p) - char *p, *end; +#define essd ((usb_endpoint_ss_comp_descriptor_t *)pp) + char *p, *pp, *end; int i; p = (char *)ifc->idesc + ifc->idesc->bLength; @@ -534,6 +535,11 @@ usbd_parse_idesc(struct usbd_device *dev if (p >= end) return (-1); + pp = p + ed->bLength; + if (pp >= end || essd->bLength == 0 || + essd->bDescriptorType != UDESC_ENDPOINT_SS_COMP) + pp = NULL; + if (dev->speed == USB_SPEED_HIGH) { unsigned int mps; @@ -557,6 +563,7 @@ usbd_parse_idesc(struct usbd_device *dev } ifc->endpoints[i].edesc = ed; + ifc->endpoints[i].esscd = essd; ifc->endpoints[i].refcnt = 0; ifc->endpoints[i].savedtoggle = 0; p += ed->bLength; @@ -564,6 +571,7 @@ usbd_parse_idesc(struct usbd_device *dev return (0); #undef ed +#undef essd } void Index: sys/dev/usb/usbdivar.h =================================================================== RCS file: /home/cvs/src/sys/dev/usb/usbdivar.h,v diff -u -p -r1.84 usbdivar.h --- sys/dev/usb/usbdivar.h 8 Oct 2024 19:42:31 -0000 1.84 +++ sys/dev/usb/usbdivar.h 27 Feb 2025 18:48:11 -0000 @@ -55,6 +55,7 @@ struct usbd_pipe; struct usbd_endpoint { usb_endpoint_descriptor_t *edesc; + usb_endpoint_ss_comp_descriptor_t *esscd; int refcnt; int savedtoggle; }; Index: sys/dev/usb/xhci.c =================================================================== RCS file: /home/cvs/src/sys/dev/usb/xhci.c,v diff -u -p -r1.135 xhci.c --- sys/dev/usb/xhci.c 8 Oct 2024 19:42:31 -0000 1.135 +++ sys/dev/usb/xhci.c 27 Feb 2025 18:51:05 -0000 @@ -1355,6 +1355,7 @@ static inline uint32_t xhci_get_txinfo(struct xhci_softc *sc, struct usbd_pipe *pipe) { usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; + usb_endpoint_ss_comp_descriptor_t *esscd = pipe->endpoint->esscd; uint32_t mep, atl, mps = UGETW(ed->wMaxPacketSize); switch (UE_GET_XFERTYPE(ed->bmAttributes)) { @@ -1364,8 +1365,10 @@ xhci_get_txinfo(struct xhci_softc *sc, s break; case UE_INTERRUPT: case UE_ISOCHRONOUS: - if (pipe->device->speed == USB_SPEED_SUPER) { - /* XXX Read the companion descriptor */ + if (esscd && pipe->device->speed >= USB_SPEED_SUPER) { + mep = UGETW(esscd->wBytesPerInterval); + atl = mep; + break; } mep = (UE_GET_TRANS(mps) + 1) * UE_GET_SIZE(mps); @@ -1441,6 +1444,7 @@ uint32_t xhci_pipe_maxburst(struct usbd_pipe *pipe) { usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; + usb_endpoint_ss_comp_descriptor_t *esscd = pipe->endpoint->esscd; uint32_t mps = UGETW(ed->wMaxPacketSize); uint8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes); uint32_t maxb = 0; @@ -1451,7 +1455,9 @@ xhci_pipe_maxburst(struct usbd_pipe *pip maxb = UE_GET_TRANS(mps); break; case USB_SPEED_SUPER: - /* XXX Read the companion descriptor */ + if (esscd && + (xfertype == UE_ISOCHRONOUS || xfertype == UE_INTERRUPT)) + maxb = esscd->bMaxBurst; default: break; }