summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Boehi <dboehi@fastmail.com>2022-04-19 20:43:18 +0200
committerTormod Volden <debian.tormod@gmail.com>2023-01-19 15:04:48 +0100
commit82d912307f8d8a2a4fc9d7bac45ada4221813105 (patch)
tree4461641729524c20754ff7755b26c16d306e7f69
parent99f1942e81caf3443f47057eba53356046a10238 (diff)
downloadlibusb-82d912307f8d8a2a4fc9d7bac45ada4221813105.tar.gz
descriptor: Add support for BOS platform descriptor parsing
Also add BOS platform descriptor dump to xusb example. Closes #1133 [Tormod: Fixed copy-pasto in Doxygen comment] Signed-off-by: Tormod Volden <debian.tormod@gmail.com>
-rw-r--r--examples/xusb.c14
-rw-r--r--libusb/descriptor.c62
-rw-r--r--libusb/libusb-1.0.def4
-rw-r--r--libusb/libusb.h39
-rw-r--r--libusb/version_nano.h2
5 files changed, 119 insertions, 2 deletions
diff --git a/examples/xusb.c b/examples/xusb.c
index 6266111..0fb5261 100644
--- a/examples/xusb.c
+++ b/examples/xusb.c
@@ -789,6 +789,20 @@ static void print_device_cap(struct libusb_bos_dev_capability_descriptor *dev_ca
}
break;
}
+ case LIBUSB_BT_PLATFORM_DESCRIPTOR: {
+ struct libusb_platform_descriptor *platform_descriptor = NULL;
+ libusb_get_platform_descriptor(NULL, dev_cap, &platform_descriptor);
+ if (platform_descriptor) {
+ printf(" Platform descriptor:\n");
+ printf(" bLength : %d\n", platform_descriptor->bLength);
+ printf(" PlatformCapabilityUUID : %s\n", uuid_to_string(platform_descriptor->PlatformCapabilityUUID));
+ display_buffer_hex(&platform_descriptor->CapabilityData[0], platform_descriptor->bLength - 20);
+ printf("\n");
+ libusb_free_platform_descriptor(platform_descriptor);
+ }
+ break;
+
+ }
default:
printf(" Unknown BOS device capability %02x:\n", dev_cap->bDevCapabilityType);
}
diff --git a/libusb/descriptor.c b/libusb/descriptor.c
index 727cf98..97e1d9a 100644
--- a/libusb/descriptor.c
+++ b/libusb/descriptor.c
@@ -1071,6 +1071,68 @@ void API_EXPORTED libusb_free_container_id_descriptor(
}
/** \ingroup libusb_desc
+ * Get a platform descriptor
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
+ * \ref libusb_capability_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
+ * LIBUSB_BT_PLATFORM_DESCRIPTOR
+ * \param platform_descriptor output location for the Platform descriptor.
+ * Only valid if 0 was returned. Must be freed with
+ * libusb_free_platform_descriptor() after use.
+ * \returns 0 on success
+ * \returns a LIBUSB_ERROR code on error
+ */
+int API_EXPORTED libusb_get_platform_descriptor(libusb_context *ctx,
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
+ struct libusb_platform_descriptor **platform_descriptor)
+{
+ struct libusb_platform_descriptor *_platform_descriptor;
+
+ if (dev_cap->bDevCapabilityType != LIBUSB_BT_PLATFORM_DESCRIPTOR) {
+ usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
+ dev_cap->bDevCapabilityType,
+ LIBUSB_BT_PLATFORM_DESCRIPTOR);
+ return LIBUSB_ERROR_INVALID_PARAM;
+ } else if (dev_cap->bLength < LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE) {
+ usbi_err(ctx, "short dev-cap descriptor read %u/%d",
+ dev_cap->bLength, LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE);
+ return LIBUSB_ERROR_IO;
+ }
+
+ _platform_descriptor = malloc(dev_cap->bLength);
+ if (!_platform_descriptor)
+ return LIBUSB_ERROR_NO_MEM;
+
+ parse_descriptor(dev_cap, "bbbbu", _platform_descriptor);
+
+ /* Capability data is located after reserved byte and 128-bit UUID */
+ uint8_t* capability_data = dev_cap->dev_capability_data + 1 + 16;
+
+ /* Capability data length is total descriptor length minus initial fields */
+ size_t capability_data_length = _platform_descriptor->bLength - (16 + 4);
+
+ memcpy(_platform_descriptor->CapabilityData, capability_data, capability_data_length);
+
+ *platform_descriptor = _platform_descriptor;
+ return LIBUSB_SUCCESS;
+}
+
+/** \ingroup libusb_desc
+ * Free a platform descriptor obtained from
+ * libusb_get_platform_descriptor().
+ * It is safe to call this function with a NULL platform_descriptor parameter,
+ * in which case the function simply returns.
+ *
+ * \param platform_descriptor the Platform descriptor to free
+ */
+void API_EXPORTED libusb_free_platform_descriptor(
+ struct libusb_platform_descriptor *platform_descriptor)
+{
+ free(platform_descriptor);
+}
+
+/** \ingroup libusb_desc
* Retrieve a string descriptor in C style ASCII.
*
* Wrapper around libusb_get_string_descriptor(). Uses the first language
diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def
index 01276aa..a12a05d 100644
--- a/libusb/libusb-1.0.def
+++ b/libusb/libusb-1.0.def
@@ -42,6 +42,8 @@ EXPORTS
libusb_free_device_list@8 = libusb_free_device_list
libusb_free_interface_association_descriptors
libusb_free_interface_association_descriptors@4 = libusb_free_interface_association_descriptors
+ libusb_free_platform_descriptor
+ libusb_free_platform_descriptor@4 = libusb_free_platform_descriptor
libusb_free_pollfds
libusb_free_pollfds@4 = libusb_free_pollfds
libusb_free_ss_endpoint_companion_descriptor
@@ -90,6 +92,8 @@ EXPORTS
libusb_get_next_timeout@8 = libusb_get_next_timeout
libusb_get_parent
libusb_get_parent@4 = libusb_get_parent
+ libusb_get_platform_descriptor
+ libusb_get_platform_descriptor@12 = libusb_get_platform_descriptor
libusb_get_pollfds
libusb_get_pollfds@4 = libusb_get_pollfds
libusb_get_port_number
diff --git a/libusb/libusb.h b/libusb/libusb.h
index 0946a55..f7b0e19 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -313,6 +313,7 @@ enum libusb_descriptor_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
/* We unwrap the BOS => define its max size */
#define LIBUSB_DT_BOS_MAX_SIZE \
@@ -531,7 +532,10 @@ enum libusb_bos_type {
LIBUSB_BT_SS_USB_DEVICE_CAPABILITY = 0x03,
/** Container ID type */
- LIBUSB_BT_CONTAINER_ID = 0x04
+ LIBUSB_BT_CONTAINER_ID = 0x04,
+
+ /** Platform descriptor */
+ LIBUSB_BT_PLATFORM_DESCRIPTOR = 0x05
};
/** \ingroup libusb_desc
@@ -975,6 +979,34 @@ struct libusb_container_id_descriptor {
uint8_t ContainerID[16];
};
+/** \ingroup libusb_desc
+ * A structure representing a Platform descriptor.
+ * This descriptor is documented in section 9.6.2.4 of the USB 3.2 specification.
+ */
+struct libusb_platform_descriptor {
+ /** Size of this descriptor (in bytes) */
+ uint8_t bLength;
+
+ /** Descriptor type. Will have value
+ * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY
+ * LIBUSB_DT_DEVICE_CAPABILITY in this context. */
+ uint8_t bDescriptorType;
+
+ /** Capability type. Will have value
+ * \ref libusb_capability_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
+ * LIBUSB_BT_CONTAINER_ID in this context. */
+ uint8_t bDevCapabilityType;
+
+ /** Reserved field */
+ uint8_t bReserved;
+
+ /** 128 bit UUID */
+ uint8_t PlatformCapabilityUUID[16];
+
+ /** Capability data (bLength - 20) */
+ uint8_t CapabilityData[ZERO_SIZED_ARRAY];
+};
+
/** \ingroup libusb_asyncio
* Setup packet for control transfers. */
#if defined(_MSC_VER) || defined(__WATCOMC__)
@@ -1483,6 +1515,11 @@ int LIBUSB_CALL libusb_get_container_id_descriptor(libusb_context *ctx,
struct libusb_container_id_descriptor **container_id);
void LIBUSB_CALL libusb_free_container_id_descriptor(
struct libusb_container_id_descriptor *container_id);
+int LIBUSB_CALL libusb_get_platform_descriptor(libusb_context *ctx,
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
+ struct libusb_platform_descriptor **platform_descriptor);
+void LIBUSB_CALL libusb_free_platform_descriptor(
+ struct libusb_platform_descriptor *platform_descriptor);
uint8_t LIBUSB_CALL libusb_get_bus_number(libusb_device *dev);
uint8_t LIBUSB_CALL libusb_get_port_number(libusb_device *dev);
int LIBUSB_CALL libusb_get_port_numbers(libusb_device *dev, uint8_t *port_numbers, int port_numbers_len);
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 259aba6..9eac25d 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11766
+#define LIBUSB_NANO 11767