git: ab18352d8f9d - main - usb: Add usbd_bos_foreach helper
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 02 Nov 2026 03:02:48 UTC
The branch main has been updated by aokblast:
URL: https://cgit.FreeBSD.org/src/commit/?id=ab18352d8f9dd26d94da1165259460ead44a9e4c
commit ab18352d8f9dd26d94da1165259460ead44a9e4c
Author: ShengYi Hung <aokblast@FreeBSD.org>
AuthorDate: 2026-05-22 16:18:57 +0000
Commit: ShengYi Hung <aokblast@FreeBSD.org>
CommitDate: 2026-11-02 03:02:11 +0000
usb: Add usbd_bos_foreach helper
Iterate the capabilities of a BOS descriptor.
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D57199
---
sys/dev/usb/usb_parse.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
sys/dev/usb/usbdi_util.h | 2 ++
2 files changed, 47 insertions(+)
diff --git a/sys/dev/usb/usb_parse.c b/sys/dev/usb/usb_parse.c
index bb592f1a4c03..7beb4dbd29a2 100644
--- a/sys/dev/usb/usb_parse.c
+++ b/sys/dev/usb/usb_parse.c
@@ -315,3 +315,48 @@ usbd_get_no_alts(struct usb_config_descriptor *cd,
}
return (n);
}
+
+/*------------------------------------------------------------------------*
+ * usbd_bos_foreach
+ *
+ * This function iterates the capabilities of a BOS descriptor. "bos"
+ * must be the complete descriptor, because "wTotalLength" is taken as
+ * the size of the buffer.
+ *
+ * Returns:
+ * NULL: End of capabilities
+ * Else: Pointer to the next capability
+ *------------------------------------------------------------------------*/
+struct usb_bos_cap_descriptor *
+usbd_bos_foreach(struct usb_bos_descriptor *bos,
+ struct usb_bos_cap_descriptor *cap)
+{
+ uint32_t offset;
+ uint32_t total;
+
+ /*
+ * No capability
+ */
+ if (bos == NULL || bos->bLength < sizeof(*bos))
+ return (NULL);
+
+ total = UGETW(bos->wTotalLength);
+
+ if (cap == NULL)
+ offset = bos->bLength;
+ else
+ offset = (uint8_t *)cap - (uint8_t *)bos + cap->bLength;
+
+ /*
+ * The returned capability must be complete
+ */
+ if (offset + sizeof(*cap) > total)
+ return (NULL);
+
+ cap = (struct usb_bos_cap_descriptor *)((uint8_t *)bos + offset);
+
+ if (cap->bLength < sizeof(*cap) || offset + cap->bLength > total)
+ return (NULL);
+
+ return (cap);
+}
diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h
index 403327e8070f..0b422387f97c 100644
--- a/sys/dev/usb/usbdi_util.h
+++ b/sys/dev/usb/usbdi_util.h
@@ -54,6 +54,8 @@ struct usb_endpoint_descriptor *usb_edesc_foreach(
struct usb_endpoint_ss_comp_descriptor *usb_ed_comp_foreach(
struct usb_config_descriptor *cd,
struct usb_endpoint_ss_comp_descriptor *ped);
+struct usb_bos_cap_descriptor *usbd_bos_foreach(struct usb_bos_descriptor *bos,
+ struct usb_bos_cap_descriptor *cap);
uint8_t usbd_get_no_descriptors(struct usb_config_descriptor *cd,
uint8_t type);
uint8_t usbd_get_no_alts(struct usb_config_descriptor *cd,