mirror of
https://github.com/shadps4-emu/ext-libusb.git
synced 2026-01-31 00:55:21 +01:00
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>
This commit is contained in:
@@ -165,6 +165,16 @@ static void display_buffer_hex(unsigned char *buffer, unsigned size)
|
|||||||
printf("\n" );
|
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
|
// The PS3 Controller is really a HID device that got its HID Report Descriptors
|
||||||
// removed by Sony
|
// removed by Sony
|
||||||
static int display_ps3_status(libusb_device_handle *handle)
|
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)
|
static int test_device(uint16_t vid, uint16_t pid)
|
||||||
{
|
{
|
||||||
libusb_device_handle *handle;
|
libusb_device_handle *handle;
|
||||||
libusb_device *dev;
|
libusb_device *dev;
|
||||||
uint8_t bus, port_path[8];
|
uint8_t bus, port_path[8];
|
||||||
|
struct libusb_bos_descriptor *bos_desc;
|
||||||
struct libusb_config_descriptor *conf_desc;
|
struct libusb_config_descriptor *conf_desc;
|
||||||
const struct libusb_endpoint_descriptor *endpoint;
|
const struct libusb_endpoint_descriptor *endpoint;
|
||||||
int i, j, k, r;
|
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[1] = dev_desc.iProduct;
|
||||||
string_index[2] = dev_desc.iSerialNumber;
|
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));
|
CALL_CHECK(libusb_get_config_descriptor(dev, 0, &conf_desc));
|
||||||
nb_ifaces = conf_desc->bNumInterfaces;
|
nb_ifaces = conf_desc->bNumInterfaces;
|
||||||
printf(" nb interfaces: %d\n", nb_ifaces);
|
printf(" nb interfaces: %d\n", nb_ifaces);
|
||||||
|
|||||||
@@ -804,6 +804,329 @@ void API_EXPORTED libusb_free_ss_endpoint_companion_descriptor(
|
|||||||
free(ep_comp);
|
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
|
/** \ingroup desc
|
||||||
* Retrieve a string descriptor in C style ASCII.
|
* Retrieve a string descriptor in C style ASCII.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -26,16 +26,26 @@ EXPORTS
|
|||||||
libusb_event_handling_ok@4 = libusb_event_handling_ok
|
libusb_event_handling_ok@4 = libusb_event_handling_ok
|
||||||
libusb_exit
|
libusb_exit
|
||||||
libusb_exit@4 = 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
|
||||||
libusb_free_config_descriptor@4 = 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
|
||||||
libusb_free_device_list@8 = 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
|
||||||
libusb_free_ss_endpoint_companion_descriptor@4 = 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
|
||||||
libusb_free_transfer@4 = 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
|
||||||
libusb_get_active_config_descriptor@8 = 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
|
||||||
libusb_get_bus_number@4 = libusb_get_bus_number
|
libusb_get_bus_number@4 = libusb_get_bus_number
|
||||||
libusb_get_config_descriptor
|
libusb_get_config_descriptor
|
||||||
@@ -44,6 +54,8 @@ EXPORTS
|
|||||||
libusb_get_config_descriptor_by_value@12 = libusb_get_config_descriptor_by_value
|
libusb_get_config_descriptor_by_value@12 = libusb_get_config_descriptor_by_value
|
||||||
libusb_get_configuration
|
libusb_get_configuration
|
||||||
libusb_get_configuration@8 = 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
|
||||||
libusb_get_device@4 = libusb_get_device
|
libusb_get_device@4 = libusb_get_device
|
||||||
libusb_get_device_address
|
libusb_get_device_address
|
||||||
@@ -70,8 +82,12 @@ EXPORTS
|
|||||||
libusb_get_port_path@16 = libusb_get_port_path
|
libusb_get_port_path@16 = libusb_get_port_path
|
||||||
libusb_get_ss_endpoint_companion_descriptor
|
libusb_get_ss_endpoint_companion_descriptor
|
||||||
libusb_get_ss_endpoint_companion_descriptor@12 = 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
|
||||||
libusb_get_string_descriptor_ascii@16 = 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
|
||||||
libusb_get_version@0 = libusb_get_version
|
libusb_get_version@0 = libusb_get_version
|
||||||
libusb_handle_events
|
libusb_handle_events
|
||||||
|
|||||||
230
libusb/libusb.h
230
libusb/libusb.h
@@ -261,6 +261,12 @@ enum libusb_descriptor_type {
|
|||||||
/** Endpoint descriptor. See libusb_endpoint_descriptor. */
|
/** Endpoint descriptor. See libusb_endpoint_descriptor. */
|
||||||
LIBUSB_DT_ENDPOINT = 0x05,
|
LIBUSB_DT_ENDPOINT = 0x05,
|
||||||
|
|
||||||
|
/** BOS descriptor */
|
||||||
|
LIBUSB_DT_BOS = 0x0f,
|
||||||
|
|
||||||
|
/** Device Capability descriptor */
|
||||||
|
LIBUSB_DT_DEVICE_CAPABILITY = 0x10,
|
||||||
|
|
||||||
/** HID descriptor */
|
/** HID descriptor */
|
||||||
LIBUSB_DT_HID = 0x21,
|
LIBUSB_DT_HID = 0x21,
|
||||||
|
|
||||||
@@ -704,6 +710,155 @@ struct libusb_ss_endpoint_companion_descriptor {
|
|||||||
uint16_t wBytesPerInterval;
|
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
|
/** \ingroup asyncio
|
||||||
* Setup packet for control transfers. */
|
* Setup packet for control transfers. */
|
||||||
struct libusb_control_setup {
|
struct libusb_control_setup {
|
||||||
@@ -831,6 +986,61 @@ enum libusb_speed {
|
|||||||
LIBUSB_SPEED_SUPER = 4,
|
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
|
/** \ingroup misc
|
||||||
* Error codes. Most libusbx functions return 0 on success or one of these
|
* Error codes. Most libusbx functions return 0 on success or one of these
|
||||||
* codes on failure.
|
* codes on failure.
|
||||||
@@ -1115,6 +1325,26 @@ int LIBUSB_CALL libusb_get_ss_endpoint_companion_descriptor(
|
|||||||
struct libusb_ss_endpoint_companion_descriptor **ep_comp);
|
struct libusb_ss_endpoint_companion_descriptor **ep_comp);
|
||||||
void LIBUSB_CALL libusb_free_ss_endpoint_companion_descriptor(
|
void LIBUSB_CALL libusb_free_ss_endpoint_companion_descriptor(
|
||||||
struct libusb_ss_endpoint_companion_descriptor *ep_comp);
|
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_bus_number(libusb_device *dev);
|
||||||
uint8_t LIBUSB_CALL libusb_get_port_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);
|
int LIBUSB_CALL libusb_get_port_numbers(libusb_device *dev, uint8_t* port_numbers, int port_numbers_len);
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define LIBUSB_NANO 10725
|
#define LIBUSB_NANO 10726
|
||||||
|
|||||||
Reference in New Issue
Block a user