The branch main has been updated by aokblast: URL: https://cgit.FreeBSD.org/src/commit/?id=20056f0e5a7fe8df85a9934150d32594d6fe84da
commit 20056f0e5a7fe8df85a9934150d32594d6fe84da Author: ShengYi Hung <aokbl...@freebsd.org> AuthorDate: 2025-07-11 03:55:37 +0000 Commit: ShengYi Hung <aokbl...@freebsd.org> CommitDate: 2025-08-06 14:05:40 +0000 libusb: implement libusb_get_platform_descriptor This adds a function introduced in libusb 1.0.27 to parse platform-specific USB descriptors, enabling access to vendor- or OS-specific information. Approved by: lwhsu (mentor) Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D51242 --- lib/libusb/libusb.3 | 15 ++++++++++++++ lib/libusb/libusb.h | 13 ++++++++++++ lib/libusb/libusb10_desc.c | 51 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/lib/libusb/libusb.3 b/lib/libusb/libusb.3 index 09140c914d68..607a7f645d95 100644 --- a/lib/libusb/libusb.3 +++ b/lib/libusb/libusb.3 @@ -544,6 +544,21 @@ libusb_free_container_id_descriptor function. .Fn libusb_free_container_id_descriptor "struct libusb_container_id_descriptor *container_id" This function is NULL safe and frees a parsed container ID descriptor given by .Fa container_id . +.Pp +.Ft int +.Fn libusb_get_platform_descriptor "struct libusb_context *ctx" "struct libusb_bos_dev_capability_descriptor *dev_cap" "struct libusb_platform_descriptor **platform_descriptor" +This function parses the platform descriptor from the descriptor given by +.Fa dev_cap +and stores a pointer to the parsed descriptor into +.Fa platform_descriptor . +Returns zero on success and a LIBUSB_ERROR code on failure. +On success the parsed platform descriptor must be freed using the +libusb_free_platform_descriptor function. +.Pp +.Ft void +.Fn libusb_free_platform_descriptor "struct libusb_platform_descriptor *platform_descriptor" +This function is NULL safe and frees a parsed platform descriptor given by +.Fa platform_descriptor . .Sh USB ASYNCHRONOUS I/O .Ft struct libusb_transfer * .Fn libusb_alloc_transfer "int iso_packets" diff --git a/lib/libusb/libusb.h b/lib/libusb/libusb.h index a2ce4136f82a..623b56fb273b 100644 --- a/lib/libusb/libusb.h +++ b/lib/libusb/libusb.h @@ -107,6 +107,7 @@ enum libusb_device_capability_type { #define LIBUSB_BT_USB_2_0_EXTENSION_SIZE 7 #define LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE 10 #define LIBUSB_BT_CONTAINER_ID_SIZE 20 +#define LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE 20 #define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f #define LIBUSB_ENDPOINT_DIR_MASK 0x80 @@ -189,6 +190,7 @@ enum libusb_bos_type { LIBUSB_BT_USB_2_0_EXTENSION = 2, LIBUSB_BT_SS_USB_DEVICE_CAPABILITY = 3, LIBUSB_BT_CONTAINER_ID = 4, + LIBUSB_BT_PLATFORM_DESCRIPTOR = 5, }; enum libusb_capability { @@ -446,6 +448,15 @@ typedef struct libusb_container_id_descriptor { uint8_t ContainerID[16]; } libusb_container_id_descriptor __aligned(sizeof(void *)); +typedef struct libusb_platform_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; + uint8_t bReserved; + uint8_t PlatformCapabilityUUID[16]; + uint8_t CapabilityData[]; +} libusb_platform_descriptor __aligned(sizeof(void *)); + typedef struct libusb_control_setup { uint8_t bmRequestType; uint8_t bRequest; @@ -554,6 +565,8 @@ int libusb_get_ss_usb_device_capability_descriptor(struct libusb_context *ctx, s void libusb_free_ss_usb_device_capability_descriptor(struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_capability); int libusb_get_container_id_descriptor(struct libusb_context *ctx, struct libusb_bos_dev_capability_descriptor *dev_cap, struct libusb_container_id_descriptor **container_id); void libusb_free_container_id_descriptor(struct libusb_container_id_descriptor *container_id); +int libusb_get_platform_descriptor(libusb_context *ctx, struct libusb_bos_dev_capability_descriptor *dev_cap, struct libusb_platform_descriptor **platform_descriptor); +void libusb_free_platform_descriptor(struct libusb_platform_descriptor *platform_descriptor); /* Asynchronous device I/O */ diff --git a/lib/libusb/libusb10_desc.c b/lib/libusb/libusb10_desc.c index 5f4c46740688..7da5c84f4ad2 100644 --- a/lib/libusb/libusb10_desc.c +++ b/lib/libusb/libusb10_desc.c @@ -711,6 +711,55 @@ void libusb_free_container_id_descriptor( struct libusb_container_id_descriptor *container_id) { - free(container_id); } + +int +libusb_get_platform_descriptor(libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *bos_cap, + struct libusb_platform_descriptor **pd) +{ + struct libusb_platform_descriptor *desc; + uint8_t *cap_data; + + if (bos_cap == NULL || + bos_cap->bDescriptorType != LIBUSB_BT_PLATFORM_DESCRIPTOR || + pd == NULL) + return (LIBUSB_ERROR_INVALID_PARAM); + + if (bos_cap->bLength < LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE) + return (LIBUSB_ERROR_IO); + + cap_data = bos_cap->dev_capability_data; + desc = calloc(1, bos_cap->bLength); + if (desc == NULL) + return (LIBUSB_ERROR_NO_MEM); + + desc->bLength = bos_cap->bLength; + desc->bDescriptorType = LIBUSB_BT_PLATFORM_DESCRIPTOR; + desc->bDevCapabilityType = bos_cap->bDevCapabilityType; + desc->bReserved = cap_data[0]; + memcpy(desc->PlatformCapabilityUUID, cap_data + 1, + sizeof(desc->PlatformCapabilityUUID)); + + /* + * UUID (16 bytes) + bReserved + */ + cap_data += sizeof(desc->PlatformCapabilityUUID) + 1; + /* + * UUID (16 bytes) + bReserved + bLength + bDescriptortype + + * bDevCapabilitytype + */ + memcpy(desc->CapabilityData, cap_data, + bos_cap->bLength - (sizeof(desc->PlatformCapabilityUUID) + 4)); + *pd = desc; + + return (LIBUSB_SUCCESS); +} + +void +libusb_free_platform_descriptor( + struct libusb_platform_descriptor *platform_descriptor) +{ + free(platform_descriptor); +}