aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-05-27 16:31:48 +0200
committerHans de Goede <hdegoede@redhat.com>2013-05-30 14:20:51 +0200
commitd7b796f1fe3d0aeee3ab2fc717eac38fec8d5caa (patch)
treecbf95240ff73b9162d8abec436b2216518ebf3b7
parentef698c633d2ecb597be58deccfa2795cc6c88e25 (diff)
downloadandroid_external_libusbx-d7b796f1fe3d0aeee3ab2fc717eac38fec8d5caa.tar.gz
android_external_libusbx-d7b796f1fe3d0aeee3ab2fc717eac38fec8d5caa.tar.bz2
android_external_libusbx-d7b796f1fe3d0aeee3ab2fc717eac38fec8d5caa.zip
Add BOS descriptor support
Based on earlier work done on this by Maya Erez <merez@codeaurora.org>, Nathan Hjelm <hjelmn@me.com> and Pete Batard <pete@akeo.ie>. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--examples/xusb.c62
-rw-r--r--libusb/descriptor.c323
-rw-r--r--libusb/libusb-1.0.def16
-rw-r--r--libusb/libusb.h230
-rw-r--r--libusb/version_nano.h2
5 files changed, 631 insertions, 2 deletions
diff --git a/examples/xusb.c b/examples/xusb.c
index e1b1931..4e2f6a5 100644
--- a/examples/xusb.c
+++ b/examples/xusb.c
@@ -165,6 +165,16 @@ static void display_buffer_hex(unsigned char *buffer, unsigned size)
printf("\n" );
}
+static char* uuid_to_string(const uint8_t* uuid)
+{
+ static char uuid_string[40];
+ if (uuid == NULL) return NULL;
+ sprintf(uuid_string, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+ uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
+ uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
+ return uuid_string;
+}
+
// The PS3 Controller is really a HID device that got its HID Report Descriptors
// removed by Sony
static int display_ps3_status(libusb_device_handle *handle)
@@ -726,11 +736,51 @@ static void read_ms_winsub_feature_descriptors(libusb_device_handle *handle, uin
}
}
+static void print_device_cap(struct libusb_bos_dev_capability_descriptor *dev_cap)
+{
+ switch(dev_cap->bDevCapabilityType) {
+ case LIBUSB_BT_USB_2_0_EXTENSION: {
+ struct libusb_usb_2_0_extension_descriptor *usb_2_0_ext = NULL;
+ libusb_get_usb_2_0_extension_descriptor(NULL, dev_cap, &usb_2_0_ext);
+ if (usb_2_0_ext) {
+ printf(" USB 2.0 extension:\n");
+ printf(" attributes : %02X\n", usb_2_0_ext->bmAttributes);
+ libusb_free_usb_2_0_extension_descriptor(usb_2_0_ext);
+ }
+ break;
+ }
+ case LIBUSB_BT_SS_USB_DEVICE_CAPABILITY: {
+ struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap = NULL;
+ libusb_get_ss_usb_device_capability_descriptor(NULL, dev_cap, &ss_usb_device_cap);
+ if (ss_usb_device_cap) {
+ printf(" USB 3.0 capabilities:\n");
+ printf(" attributes : %02X\n", ss_usb_device_cap->bmAttributes);
+ printf(" supported speeds : %04X\n", ss_usb_device_cap->wSpeedSupported);
+ printf(" supported functionality: %02X\n", ss_usb_device_cap->bFunctionalitySupport);
+ libusb_free_ss_usb_device_capability_descriptor(ss_usb_device_cap);
+ }
+ break;
+ }
+ case LIBUSB_BT_CONTAINER_ID: {
+ struct libusb_container_id_descriptor *container_id = NULL;
+ libusb_get_container_id_descriptor(NULL, dev_cap, &container_id);
+ if (container_id) {
+ printf(" Container ID:\n %s\n", uuid_to_string(container_id->ContainerID));
+ libusb_free_container_id_descriptor(container_id);
+ }
+ break;
+ }
+ default:
+ printf(" Unknown BOS device capability %02x:\n", dev_cap->bDevCapabilityType);
+ }
+}
+
static int test_device(uint16_t vid, uint16_t pid)
{
libusb_device_handle *handle;
libusb_device *dev;
uint8_t bus, port_path[8];
+ struct libusb_bos_descriptor *bos_desc;
struct libusb_config_descriptor *conf_desc;
const struct libusb_endpoint_descriptor *endpoint;
int i, j, k, r;
@@ -784,7 +834,17 @@ static int test_device(uint16_t vid, uint16_t pid)
string_index[1] = dev_desc.iProduct;
string_index[2] = dev_desc.iSerialNumber;
- printf("\nReading configuration descriptors:\n");
+ printf("\nReading BOS descriptor: ");
+ if (libusb_get_bos_descriptor(handle, &bos_desc) == LIBUSB_SUCCESS) {
+ printf("%d caps\n", bos_desc->bNumDeviceCaps);
+ for (i = 0; i < bos_desc->bNumDeviceCaps; i++)
+ print_device_cap(bos_desc->dev_capability[i]);
+ libusb_free_bos_descriptor(bos_desc);
+ } else {
+ printf("no descriptor\n");
+ }
+
+ printf("\nReading first configuration descriptor:\n");
CALL_CHECK(libusb_get_config_descriptor(dev, 0, &conf_desc));
nb_ifaces = conf_desc->bNumInterfaces;
printf(" nb interfaces: %d\n", nb_ifaces);
diff --git a/libusb/descriptor.c b/libusb/descriptor.c
index 14482ca..161be36 100644
--- a/libusb/descriptor.c
+++ b/libusb/descriptor.c
@@ -804,6 +804,329 @@ void API_EXPORTED libusb_free_ss_endpoint_companion_descriptor(
free(ep_comp);
}
+static int parse_bos(struct libusb_context *ctx,
+ struct libusb_bos_descriptor **bos,
+ unsigned char *buffer, int size, int host_endian)
+{
+ struct libusb_bos_descriptor bos_header, *_bos;
+ struct libusb_bos_dev_capability_descriptor dev_cap;
+ int i;
+
+ if (size < LIBUSB_DT_BOS_SIZE) {
+ usbi_err(ctx, "short bos descriptor read %d/%d",
+ size, LIBUSB_DT_BOS_SIZE);
+ return LIBUSB_ERROR_IO;
+ }
+
+ usbi_parse_descriptor(buffer, "bbwb", &bos_header, host_endian);
+ if (bos_header.bDescriptorType != LIBUSB_DT_BOS) {
+ usbi_err(ctx, "unexpected descriptor %x (expected %x)",
+ bos_header.bDescriptorType, LIBUSB_DT_BOS);
+ return LIBUSB_ERROR_IO;
+ }
+ if (bos_header.bLength < LIBUSB_DT_BOS_SIZE) {
+ usbi_err(ctx, "invalid bos bLength (%d)", bos_header.bLength);
+ return LIBUSB_ERROR_IO;
+ }
+ if (bos_header.bLength > size) {
+ usbi_err(ctx, "short bos descriptor read %d/%d",
+ size, bos_header.bLength);
+ return LIBUSB_ERROR_IO;
+ }
+
+ _bos = calloc (1,
+ sizeof(*_bos) + bos_header.bNumDeviceCaps * sizeof(void *));
+ if (!_bos)
+ return LIBUSB_ERROR_NO_MEM;
+
+ usbi_parse_descriptor(buffer, "bbwb", _bos, host_endian);
+ buffer += bos_header.bLength;
+ size -= bos_header.bLength;
+
+ /* Get the device capability descriptors */
+ for (i = 0; i < bos_header.bNumDeviceCaps; i++) {
+ if (size < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) {
+ usbi_warn(ctx, "short dev-cap descriptor read %d/%d",
+ size, LIBUSB_DT_DEVICE_CAPABILITY_SIZE);
+ break;
+ }
+ usbi_parse_descriptor(buffer, "bbb", &dev_cap, host_endian);
+ if (dev_cap.bDescriptorType != LIBUSB_DT_DEVICE_CAPABILITY) {
+ usbi_warn(ctx, "unexpected descriptor %x (expected %x)",
+ dev_cap.bDescriptorType, LIBUSB_DT_DEVICE_CAPABILITY);
+ break;
+ }
+ if (dev_cap.bLength < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) {
+ usbi_err(ctx, "invalid dev-cap bLength (%d)",
+ dev_cap.bLength);
+ libusb_free_bos_descriptor(_bos);
+ return LIBUSB_ERROR_IO;
+ }
+ if (dev_cap.bLength > size) {
+ usbi_warn(ctx, "short dev-cap descriptor read %d/%d",
+ size, dev_cap.bLength);
+ break;
+ }
+
+ _bos->dev_capability[i] = malloc(dev_cap.bLength);
+ if (!_bos->dev_capability[i]) {
+ libusb_free_bos_descriptor(_bos);
+ return LIBUSB_ERROR_NO_MEM;
+ }
+ memcpy(_bos->dev_capability[i], buffer, dev_cap.bLength);
+ buffer += dev_cap.bLength;
+ size -= dev_cap.bLength;
+ }
+ _bos->bNumDeviceCaps = i;
+ *bos = _bos;
+
+ return LIBUSB_SUCCESS;
+}
+
+/** \ingroup desc
+ * Get a Binary Object Store (BOS) descriptor
+ * This is a BLOCKING function, which will send requests to the device.
+ *
+ * \param handle the handle of an open libusb device
+ * \param bos output location for the BOS descriptor. Only valid if 0 was returned.
+ * Must be freed with \ref libusb_free_bos_descriptor() after use.
+ * \returns 0 on success
+ * \returns LIBUSB_ERROR_NOT_FOUND if the device doesn't have a BOS descriptor
+ * \returns another LIBUSB_ERROR code on error
+ */
+int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *handle,
+ struct libusb_bos_descriptor **bos)
+{
+ struct libusb_bos_descriptor _bos;
+ uint8_t bos_header[LIBUSB_DT_BOS_SIZE] = {0};
+ unsigned char *bos_data = NULL;
+ const int host_endian = 0;
+ int r;
+
+ /* Read the BOS. This generates 2 requests on the bus,
+ * one for the header, and one for the full BOS */
+ r = libusb_get_descriptor(handle, LIBUSB_DT_BOS, 0, bos_header,
+ LIBUSB_DT_BOS_SIZE);
+ if (r < 0) {
+ usbi_err(handle->dev->ctx, "failed to read BOS (%d)", r);
+ return r;
+ }
+ if (r < LIBUSB_DT_BOS_SIZE) {
+ usbi_err(handle->dev->ctx, "short BOS read %d/%d",
+ r, LIBUSB_DT_BOS_SIZE);
+ return LIBUSB_ERROR_IO;
+ }
+
+ usbi_parse_descriptor(bos_header, "bbwb", &_bos, host_endian);
+ usbi_dbg("found BOS descriptor: size %d bytes, %d capabilities",
+ _bos.wTotalLength, _bos.bNumDeviceCaps);
+ bos_data = calloc(_bos.wTotalLength, 1);
+ if (bos_data == NULL)
+ return LIBUSB_ERROR_NO_MEM;
+
+ r = libusb_get_descriptor(handle, LIBUSB_DT_BOS, 0, bos_data,
+ _bos.wTotalLength);
+ if (r >= 0)
+ r = parse_bos(handle->dev->ctx, bos, bos_data, r, host_endian);
+ else
+ usbi_err(handle->dev->ctx, "failed to read BOS (%d)", r);
+
+ free(bos_data);
+ return r;
+}
+
+/** \ingroup desc
+ * Free a BOS descriptor obtained from libusb_get_bos_descriptor().
+ * It is safe to call this function with a NULL bos parameter, in which
+ * case the function simply returns.
+ *
+ * \param bos the BOS descriptor to free
+ */
+void API_EXPORTED libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos)
+{
+ int i;
+
+ if (!bos)
+ return;
+
+ for (i = 0; i < bos->bNumDeviceCaps; i++)
+ free(bos->dev_capability[i]);
+ free(bos);
+}
+
+/** \ingroup desc
+ * Get an USB 2.0 Extension 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_USB_2_0_EXTENSION
+ * LIBUSB_BT_USB_2_0_EXTENSION
+ * \param usb_2_0_extension output location for the USB 2.0 Extension
+ * descriptor. Only valid if 0 was returned. Must be freed with
+ * libusb_free_usb_2_0_extension_descriptor() after use.
+ * \returns 0 on success
+ * \returns a LIBUSB_ERROR code on error
+ */
+int API_EXPORTED libusb_get_usb_2_0_extension_descriptor(
+ struct libusb_context *ctx,
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
+ struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension)
+{
+ struct libusb_usb_2_0_extension_descriptor *_usb_2_0_extension;
+ const int host_endian = 0;
+
+ if (dev_cap->bDevCapabilityType != LIBUSB_BT_USB_2_0_EXTENSION) {
+ usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)",
+ dev_cap->bDevCapabilityType,
+ LIBUSB_BT_USB_2_0_EXTENSION);
+ return LIBUSB_ERROR_INVALID_PARAM;
+ }
+ if (dev_cap->bLength < LIBUSB_BT_USB_2_0_EXTENSION_SIZE) {
+ usbi_err(ctx, "short dev-cap descriptor read %d/%d",
+ dev_cap->bLength, LIBUSB_BT_USB_2_0_EXTENSION_SIZE);
+ return LIBUSB_ERROR_IO;
+ }
+
+ _usb_2_0_extension = malloc(sizeof(*_usb_2_0_extension));
+ if (!_usb_2_0_extension)
+ return LIBUSB_ERROR_NO_MEM;
+
+ usbi_parse_descriptor((unsigned char *)dev_cap, "bbbd",
+ _usb_2_0_extension, host_endian);
+
+ *usb_2_0_extension = _usb_2_0_extension;
+ return LIBUSB_SUCCESS;
+}
+
+/** \ingroup desc
+ * Free a USB 2.0 Extension descriptor obtained from
+ * libusb_get_usb_2_0_extension_descriptor().
+ * It is safe to call this function with a NULL usb_2_0_extension parameter,
+ * in which case the function simply returns.
+ *
+ * \param usb_2_0_extension the USB 2.0 Extension descriptor to free
+ */
+void API_EXPORTED libusb_free_usb_2_0_extension_descriptor(
+ struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension)
+{
+ free(usb_2_0_extension);
+}
+
+/** \ingroup desc
+ * Get a SuperSpeed USB Device Capability 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_SS_USB_DEVICE_CAPABILITY
+ * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
+ * \param ss_usb_device_cap output location for the SuperSpeed USB Device
+ * Capability descriptor. Only valid if 0 was returned. Must be freed with
+ * libusb_free_ss_usb_device_capability_descriptor() after use.
+ * \returns 0 on success
+ * \returns a LIBUSB_ERROR code on error
+ */
+int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor(
+ struct libusb_context *ctx,
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
+ struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap)
+{
+ struct libusb_ss_usb_device_capability_descriptor *_ss_usb_device_cap;
+ const int host_endian = 0;
+
+ if (dev_cap->bDevCapabilityType != LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) {
+ usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)",
+ dev_cap->bDevCapabilityType,
+ LIBUSB_BT_SS_USB_DEVICE_CAPABILITY);
+ return LIBUSB_ERROR_INVALID_PARAM;
+ }
+ if (dev_cap->bLength < LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) {
+ usbi_err(ctx, "short dev-cap descriptor read %d/%d",
+ dev_cap->bLength, LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE);
+ return LIBUSB_ERROR_IO;
+ }
+
+ _ss_usb_device_cap = malloc(sizeof(*_ss_usb_device_cap));
+ if (!_ss_usb_device_cap)
+ return LIBUSB_ERROR_NO_MEM;
+
+ usbi_parse_descriptor((unsigned char *)dev_cap, "bbbbwbbw",
+ _ss_usb_device_cap, host_endian);
+
+ *ss_usb_device_cap = _ss_usb_device_cap;
+ return LIBUSB_SUCCESS;
+}
+
+/** \ingroup desc
+ * Free a SuperSpeed USB Device Capability descriptor obtained from
+ * libusb_get_ss_usb_device_capability_descriptor().
+ * It is safe to call this function with a NULL ss_usb_device_cap
+ * parameter, in which case the function simply returns.
+ *
+ * \param ss_usb_device_cap the USB 2.0 Extension descriptor to free
+ */
+void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor(
+ struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap)
+{
+ free(ss_usb_device_cap);
+}
+
+/** \ingroup desc
+ * Get a Container ID 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_CONTAINER_ID
+ * LIBUSB_BT_CONTAINER_ID
+ * \param container_id output location for the Container ID descriptor.
+ * Only valid if 0 was returned. Must be freed with
+ * libusb_free_container_id_descriptor() after use.
+ * \returns 0 on success
+ * \returns a LIBUSB_ERROR code on error
+ */
+int API_EXPORTED libusb_get_container_id_descriptor(struct libusb_context *ctx,
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
+ struct libusb_container_id_descriptor **container_id)
+{
+ struct libusb_container_id_descriptor *_container_id;
+ const int host_endian = 0;
+
+ if (dev_cap->bDevCapabilityType != LIBUSB_BT_CONTAINER_ID) {
+ usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)",
+ dev_cap->bDevCapabilityType,
+ LIBUSB_BT_CONTAINER_ID);
+ return LIBUSB_ERROR_INVALID_PARAM;
+ }
+ if (dev_cap->bLength < LIBUSB_BT_CONTAINER_ID_SIZE) {
+ usbi_err(ctx, "short dev-cap descriptor read %d/%d",
+ dev_cap->bLength, LIBUSB_BT_CONTAINER_ID_SIZE);
+ return LIBUSB_ERROR_IO;
+ }
+
+ _container_id = malloc(sizeof(*_container_id));
+ if (!_container_id)
+ return LIBUSB_ERROR_NO_MEM;
+
+ usbi_parse_descriptor((unsigned char *)dev_cap, "bbbbu",
+ _container_id, host_endian);
+
+ *container_id = _container_id;
+ return LIBUSB_SUCCESS;
+}
+
+/** \ingroup desc
+ * Free a Container ID descriptor obtained from
+ * libusb_get_container_id_descriptor().
+ * It is safe to call this function with a NULL container_id parameter,
+ * in which case the function simply returns.
+ *
+ * \param container_id the USB 2.0 Extension descriptor to free
+ */
+void API_EXPORTED libusb_free_container_id_descriptor(
+ struct libusb_container_id_descriptor *container_id)
+{
+ free(container_id);
+}
+
/** \ingroup desc
* Retrieve a string descriptor in C style ASCII.
*
diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def
index 52047ea..7166d47 100644
--- a/libusb/libusb-1.0.def
+++ b/libusb/libusb-1.0.def
@@ -26,16 +26,26 @@ EXPORTS
libusb_event_handling_ok@4 = libusb_event_handling_ok
libusb_exit
libusb_exit@4 = libusb_exit
+ libusb_free_bos_descriptor
+ libusb_free_bos_descriptor@4 = libusb_free_bos_descriptor
libusb_free_config_descriptor
libusb_free_config_descriptor@4 = libusb_free_config_descriptor
+ libusb_free_container_id_descriptor
+ libusb_free_container_id_descriptor@4 = libusb_free_container_id_descriptor
libusb_free_device_list
libusb_free_device_list@8 = libusb_free_device_list
libusb_free_ss_endpoint_companion_descriptor
libusb_free_ss_endpoint_companion_descriptor@4 = libusb_free_ss_endpoint_companion_descriptor
+ libusb_free_ss_usb_device_capability_descriptor
+ libusb_free_ss_usb_device_capability_descriptor@4 = libusb_free_ss_usb_device_capability_descriptor
libusb_free_transfer
libusb_free_transfer@4 = libusb_free_transfer
+ libusb_free_usb_2_0_extension_descriptor
+ libusb_free_usb_2_0_extension_descriptor@4 = libusb_free_usb_2_0_extension_descriptor
libusb_get_active_config_descriptor
libusb_get_active_config_descriptor@8 = libusb_get_active_config_descriptor
+ libusb_get_bos_descriptor
+ libusb_get_bos_descriptor@8 = libusb_get_bos_descriptor
libusb_get_bus_number
libusb_get_bus_number@4 = libusb_get_bus_number
libusb_get_config_descriptor
@@ -44,6 +54,8 @@ EXPORTS
libusb_get_config_descriptor_by_value@12 = libusb_get_config_descriptor_by_value
libusb_get_configuration
libusb_get_configuration@8 = libusb_get_configuration
+ libusb_get_container_id_descriptor
+ libusb_get_container_id_descriptor@12 = libusb_get_container_id_descriptor
libusb_get_device
libusb_get_device@4 = libusb_get_device
libusb_get_device_address
@@ -70,8 +82,12 @@ EXPORTS
libusb_get_port_path@16 = libusb_get_port_path
libusb_get_ss_endpoint_companion_descriptor
libusb_get_ss_endpoint_companion_descriptor@12 = libusb_get_ss_endpoint_companion_descriptor
+ libusb_get_ss_usb_device_capability_descriptor
+ libusb_get_ss_usb_device_capability_descriptor@12 = libusb_get_ss_usb_device_capability_descriptor
libusb_get_string_descriptor_ascii
libusb_get_string_descriptor_ascii@16 = libusb_get_string_descriptor_ascii
+ libusb_get_usb_2_0_extension_descriptor
+ libusb_get_usb_2_0_extension_descriptor@12 = libusb_get_usb_2_0_extension_descriptor
libusb_get_version
libusb_get_version@0 = libusb_get_version
libusb_handle_events
diff --git a/libusb/libusb.h b/libusb/libusb.h
index 593dc09..d733c46 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -261,6 +261,12 @@ enum libusb_descriptor_type {
/** Endpoint descriptor. See libusb_endpoint_descriptor. */
LIBUSB_DT_ENDPOINT = 0x05,
+ /** BOS descriptor */
+ LIBUSB_DT_BOS = 0x0f,
+
+ /** Device Capability descriptor */
+ LIBUSB_DT_DEVICE_CAPABILITY = 0x10,
+
/** HID descriptor */
LIBUSB_DT_HID = 0x21,
@@ -704,6 +710,155 @@ struct libusb_ss_endpoint_companion_descriptor {
uint16_t wBytesPerInterval;
};
+/** \ingroup desc
+ * A generic representation of a BOS Device Capability descriptor. It is
+ * advised to check bDevCapabilityType and call the matching
+ * libusb_get_*_descriptor function to get a structure fully matching the type.
+ */
+struct libusb_bos_dev_capability_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;
+ /** Device Capability type */
+ uint8_t bDevCapabilityType;
+ /** Device Capability data (bLength - 3 bytes) */
+ uint8_t dev_capability_data
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+ [] /* valid C99 code */
+#else
+ [0] /* non-standard, but usually working code */
+#endif
+ ;
+};
+
+/** \ingroup desc
+ * A structure representing the Binary Device Object Store (BOS) descriptor.
+ * This descriptor is documented in section 9.6.2 of the USB 3.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_bos_descriptor {
+ /** Size of this descriptor (in bytes) */
+ uint8_t bLength;
+
+ /** Descriptor type. Will have value
+ * \ref libusb_descriptor_type::LIBUSB_DT_BOS LIBUSB_DT_BOS
+ * in this context. */
+ uint8_t bDescriptorType;
+
+ /** Length of this descriptor and all of its sub descriptors */
+ uint16_t wTotalLength;
+
+ /** The number of separate device capability descriptors in
+ * the BOS */
+ uint8_t bNumDeviceCaps;
+
+ /** bNumDeviceCap Device Capability Descriptors */
+ struct libusb_bos_dev_capability_descriptor *dev_capability
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+ [] /* valid C99 code */
+#else
+ [0] /* non-standard, but usually working code */
+#endif
+ ;
+};
+
+/** \ingroup desc
+ * A structure representing the USB 2.0 Extension descriptor
+ * This descriptor is documented in section 9.6.2.1 of the USB 3.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_usb_2_0_extension_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_USB_2_0_EXTENSION
+ * LIBUSB_BT_USB_2_0_EXTENSION in this context. */
+ uint8_t bDevCapabilityType;
+
+ /** Bitmap encoding of supported device level features.
+ * A value of one in a bit location indicates a feature is
+ * supported; a value of zero indicates it is not supported.
+ * See \ref libusb_usb_2_0_extension_attributes. */
+ uint32_t bmAttributes;
+};
+
+/** \ingroup desc
+ * A structure representing the SuperSpeed USB Device Capability descriptor
+ * This descriptor is documented in section 9.6.2.2 of the USB 3.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_ss_usb_device_capability_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_SS_USB_DEVICE_CAPABILITY
+ * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY in this context. */
+ uint8_t bDevCapabilityType;
+
+ /** Bitmap encoding of supported device level features.
+ * A value of one in a bit location indicates a feature is
+ * supported; a value of zero indicates it is not supported.
+ * See \ref libusb_ss_usb_device_capability_attributes. */
+ uint8_t bmAttributes;
+
+ /** Bitmap encoding of the speed supported by this device when
+ * operating in SuperSpeed mode. See \ref libusb_supported_speed. */
+ uint16_t wSpeedSupported;
+
+ /** The lowest speed at which all the functionality supported
+ * by the device is available to the user. For example if the
+ * device supports all its functionality when connected at
+ * full speed and above then it sets this value to 1. */
+ uint8_t bFunctionalitySupport;
+
+ /** U1 Device Exit Latency. */
+ uint8_t bU1DevExitLat;
+
+ /** U2 Device Exit Latency. */
+ uint16_t bU2DevExitLat;
+};
+
+/** \ingroup desc
+ * A structure representing the Container ID descriptor.
+ * This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification.
+ * All multiple-byte fields, except UUIDs, are represented in host-endian format.
+ */
+struct libusb_container_id_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_CONTAINER_ID
+ * LIBUSB_BT_CONTAINER_ID in this context. */
+ uint8_t bDevCapabilityType;
+
+ /** Reserved field */
+ uint8_t bReserved;
+
+ /** 128 bit UUID */
+ uint8_t ContainerID[16];
+};
+
/** \ingroup asyncio
* Setup packet for control transfers. */
struct libusb_control_setup {
@@ -831,6 +986,61 @@ enum libusb_speed {
LIBUSB_SPEED_SUPER = 4,
};
+/** \ingroup dev
+ * Supported speeds (wSpeedSupported) bitfield. Indicates what
+ * speeds the device supports.
+ */
+enum libusb_supported_speed {
+ /** Low speed operation supported (1.5MBit/s). */
+ LIBUSB_LOW_SPEED_OPERATION = 1,
+
+ /** Full speed operation supported (12MBit/s). */
+ LIBUSB_FULL_SPEED_OPERATION = 2,
+
+ /** High speed operation supported (480MBit/s). */
+ LIBUSB_HIGH_SPEED_OPERATION = 4,
+
+ /** Superspeed operation supported (5000MBit/s). */
+ LIBUSB_SUPER_SPEED_OPERATION = 8,
+};
+
+/** \ingroup dev
+ * Masks for the bits of the
+ * \ref libusb_usb_2_0_extension_descriptor::bmAttributes "bmAttributes" field
+ * of the USB 2.0 Extension descriptor.
+ */
+enum libusb_usb_2_0_extension_attributes {
+ /** Supports Link Power Management (LPM) */
+ LIBUSB_BM_LPM_SUPPORT = 2,
+};
+
+/** \ingroup dev
+ * Masks for the bits of the
+ * \ref libusb_ss_usb_device_capability_descriptor::bmAttributes "bmAttributes" field
+ * field of the SuperSpeed USB Device Capability descriptor.
+ */
+enum libusb_ss_usb_device_capability_attributes {
+ /** Supports Latency Tolerance Messages (LTM) */
+ LIBUSB_BM_LTM_SUPPORT = 2,
+};
+
+/** \ingroup dev
+ * USB capability types
+ */
+enum libusb_bos_type {
+ /** Wireless USB device capability */
+ LIBUSB_BT_WIRELESS_USB_DEVICE_CAPABILITY = 1,
+
+ /** USB 2.0 extensions */
+ LIBUSB_BT_USB_2_0_EXTENSION = 2,
+
+ /** SuperSpeed USB device capability */
+ LIBUSB_BT_SS_USB_DEVICE_CAPABILITY = 3,
+
+ /** Container ID type */
+ LIBUSB_BT_CONTAINER_ID = 4,
+};
+
/** \ingroup misc
* Error codes. Most libusbx functions return 0 on success or one of these
* codes on failure.
@@ -1115,6 +1325,26 @@ int LIBUSB_CALL libusb_get_ss_endpoint_companion_descriptor(
struct libusb_ss_endpoint_companion_descriptor **ep_comp);
void LIBUSB_CALL libusb_free_ss_endpoint_companion_descriptor(
struct libusb_ss_endpoint_companion_descriptor *ep_comp);
+int LIBUSB_CALL libusb_get_bos_descriptor(libusb_device_handle *handle,
+ struct libusb_bos_descriptor **bos);
+void LIBUSB_CALL libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos);
+int LIBUSB_CALL libusb_get_usb_2_0_extension_descriptor(
+ struct libusb_context *ctx,
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
+ struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension);
+void LIBUSB_CALL libusb_free_usb_2_0_extension_descriptor(
+ struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension);
+int LIBUSB_CALL libusb_get_ss_usb_device_capability_descriptor(
+ struct libusb_context *ctx,
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
+ struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap);
+void LIBUSB_CALL libusb_free_ss_usb_device_capability_descriptor(
+ struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap);
+int LIBUSB_CALL 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_CALL libusb_free_container_id_descriptor(
+ struct libusb_container_id_descriptor *container_id);
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 d69b0cc..8cbe78f 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 10725
+#define LIBUSB_NANO 10726