git: 2f79adc28976 - main - usb: Implement usbd_req_get_bos_descriptor helper

From: ShengYi Hung <aokblast_at_FreeBSD.org>
Date: Mon, 02 Nov 2026 03:02:51 UTC
The branch main has been updated by aokblast:

URL: https://cgit.FreeBSD.org/src/commit/?id=2f79adc28976870f4f5ad3a2ce61f2f8da0eb131

commit 2f79adc28976870f4f5ad3a2ce61f2f8da0eb131
Author:     ShengYi Hung <aokblast@FreeBSD.org>
AuthorDate: 2026-05-22 16:21:06 +0000
Commit:     ShengYi Hung <aokblast@FreeBSD.org>
CommitDate: 2026-11-02 03:02:11 +0000

    usb: Implement usbd_req_get_bos_descriptor helper
    
    Get the header or the complete BOS descriptor of SS+ devices.
    
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D57202
---
 sys/dev/usb/usb.h         |  3 +++
 sys/dev/usb/usb_request.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/usb/usb_request.h |  4 +++
 3 files changed, 69 insertions(+)

diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h
index 8eb36a24bbcd..90078df11361 100644
--- a/sys/dev/usb/usb.h
+++ b/sys/dev/usb/usb.h
@@ -309,6 +309,9 @@ struct usb_device_descriptor {
 } __packed;
 typedef struct usb_device_descriptor usb_device_descriptor_t;
 
+/* Maximum sane wTotalLength for a BOS descriptor */
+#define	USB_BOS_DESC_MAX_LEN	4096
+
 /* Binary Device Object Store (BOS) */
 struct usb_bos_descriptor {
 	uByte	bLength;
diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c
index df6dadae541b..2a57c75a85d2 100644
--- a/sys/dev/usb/usb_request.c
+++ b/sys/dev/usb/usb_request.c
@@ -1535,6 +1535,68 @@ usbd_req_get_ss_hub_descriptor(struct usb_device *udev, struct mtx *mtx,
 	return (usbd_do_request(udev, mtx, &req, hd));
 }
 
+/*------------------------------------------------------------------------*
+ *	usbd_req_get_bos_descriptor
+ *
+ * Returns:
+ *    0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+usb_error_t
+usbd_req_get_bos_descriptor(struct usb_device *udev, struct mtx *mtx,
+    struct usb_bos_descriptor *bd)
+{
+	return (usbd_req_get_desc(udev, mtx, NULL, bd, sizeof(*bd),
+	    sizeof(*bd), 0, UDESC_BOS, 0, 3));
+}
+
+/*------------------------------------------------------------------------*
+ *	usbd_req_get_bos_descriptor_full
+ *
+ * Returns:
+ *    0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+usb_error_t
+usbd_req_get_bos_descriptor_full(struct usb_device *udev, struct mtx *mtx,
+    struct usb_bos_descriptor **bdp)
+{
+	struct usb_bos_descriptor bd;
+	struct usb_bos_descriptor *bdesc;
+	uint32_t len;
+	usb_error_t err;
+
+	*bdp = NULL;
+
+	err = usbd_req_get_bos_descriptor(udev, mtx, &bd);
+	if (err)
+		return (err);
+
+	len = UGETW(bd.wTotalLength);
+	if (len < sizeof(bd) || len > USB_BOS_DESC_MAX_LEN) {
+		DPRINTFN(0, "BOS descriptor wTotalLength %u is invalid\n",
+		    len);
+		return (USB_ERR_INVAL);
+	}
+
+	bdesc = malloc(len, M_USBDEV, M_WAITOK | M_ZERO);
+	if (bdesc == NULL)
+		return (USB_ERR_NOMEM);
+	err = usbd_req_get_desc(udev, mtx, NULL, bdesc, len, len, 0,
+	    UDESC_BOS, 0, 3);
+	if (err) {
+		free(bdesc, M_USBDEV);
+		return (err);
+	}
+	if (UGETW(bdesc->wTotalLength) != len) {
+		DPRINTFN(0, "BOS descriptor length changed\n");
+		free(bdesc, M_USBDEV);
+		return (USB_ERR_INVAL);
+	}
+	*bdp = bdesc;
+	return (0);
+}
+
 /*------------------------------------------------------------------------*
  *	usbd_req_get_hub_status
  *
diff --git a/sys/dev/usb/usb_request.h b/sys/dev/usb/usb_request.h
index f7ccd84eb69c..8e7d3632322e 100644
--- a/sys/dev/usb/usb_request.h
+++ b/sys/dev/usb/usb_request.h
@@ -60,6 +60,10 @@ usb_error_t usbd_req_get_hub_descriptor(struct usb_device *udev,
 usb_error_t usbd_req_get_ss_hub_descriptor(struct usb_device *udev,
 		    struct mtx *mtx, struct usb_hub_ss_descriptor *hd,
 		    uint8_t nports);
+usb_error_t usbd_req_get_bos_descriptor(struct usb_device *udev,
+		    struct mtx *mtx, struct usb_bos_descriptor *desc);
+usb_error_t usbd_req_get_bos_descriptor_full(struct usb_device *udev,
+		    struct mtx *mtx, struct usb_bos_descriptor **pdesc);
 usb_error_t usbd_req_get_hub_status(struct usb_device *udev, struct mtx *mtx,
 		    struct usb_hub_status *st);
 usb_error_t usbd_req_get_port_status(struct usb_device *udev, struct mtx *mtx,