summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorkevans <kevans@FreeBSD.org>2018-01-18 21:39:03 +0000
committerkevans <kevans@FreeBSD.org>2018-01-18 21:39:03 +0000
commitf1935666e0471636cfda55938bd57fff70648277 (patch)
treedbf1f78b4e683b16230a78ca0cbe4cfc2f74cdcb /lib
parent67ec24fb218378a0c90c1016ae39f7e9263d99f5 (diff)
downloadFreeBSD-src-f1935666e0471636cfda55938bd57fff70648277.zip
FreeBSD-src-f1935666e0471636cfda55938bd57fff70648277.tar.gz
MFC r322322: Expose device caps as libusb_bos_descriptor::dev_capability
Some libusb consumers in Linux-land (in this case, libusb4java) expect a dev_capability member that they can use to enumerate the device capabilities. No particular layout is expected of this, just that it can be traversed using the bLength member until bNumDeviceCapabilities are read and that the consumer may then use one of the libusb_get_*_descriptor methods to extract specific (usb 2.0 vs. ss) capability information.
Diffstat (limited to 'lib')
-rw-r--r--lib/libusb/libusb.h1
-rw-r--r--lib/libusb/libusb10_desc.c28
2 files changed, 27 insertions, 2 deletions
diff --git a/lib/libusb/libusb.h b/lib/libusb/libusb.h
index 44bdb4b..42f55ab 100644
--- a/lib/libusb/libusb.h
+++ b/lib/libusb/libusb.h
@@ -388,6 +388,7 @@ typedef struct libusb_bos_descriptor {
uint8_t bNumDeviceCapabilities;
struct libusb_usb_2_0_device_capability_descriptor *usb_2_0_ext_cap;
struct libusb_ss_usb_device_capability_descriptor *ss_usb_cap;
+ struct libusb_bos_dev_capability_descriptor **dev_capability;
} libusb_bos_descriptor __aligned(sizeof(void *));
typedef struct libusb_usb_2_0_extension_descriptor {
diff --git a/lib/libusb/libusb10_desc.c b/lib/libusb/libusb10_desc.c
index c214195..bbc3429 100644
--- a/lib/libusb/libusb10_desc.c
+++ b/lib/libusb/libusb10_desc.c
@@ -433,6 +433,7 @@ libusb_parse_bos_descriptor(const void *buf, int len,
struct libusb_bos_descriptor *ptr;
struct libusb_usb_2_0_device_capability_descriptor *dcap_20 = NULL;
struct libusb_ss_usb_device_capability_descriptor *ss_cap = NULL;
+ uint8_t index = 0;
if (buf == NULL || bos == NULL || len < 1)
return (LIBUSB_ERROR_INVALID_PARAM);
@@ -453,7 +454,8 @@ libusb_parse_bos_descriptor(const void *buf, int len,
break;
if (dlen >= LIBUSB_DT_BOS_SIZE &&
- dtype == LIBUSB_DT_BOS) {
+ dtype == LIBUSB_DT_BOS &&
+ ptr == NULL) {
ptr = malloc(sizeof(*ptr) + sizeof(*dcap_20) +
sizeof(*ss_cap));
@@ -470,6 +472,11 @@ libusb_parse_bos_descriptor(const void *buf, int len,
ptr->bNumDeviceCapabilities = ((const uint8_t *)buf)[4];
ptr->usb_2_0_ext_cap = NULL;
ptr->ss_usb_cap = NULL;
+ ptr->dev_capability = calloc(ptr->bNumDeviceCapabilities, sizeof(void *));
+ if (ptr->dev_capability == NULL) {
+ free(ptr);
+ return (LIBUSB_ERROR_NO_MEM);
+ }
dcap_20 = (void *)(ptr + 1);
ss_cap = (void *)(dcap_20 + 1);
@@ -477,6 +484,15 @@ libusb_parse_bos_descriptor(const void *buf, int len,
if (dlen >= 3 &&
ptr != NULL &&
dtype == LIBUSB_DT_DEVICE_CAPABILITY) {
+ if (index != ptr->bNumDeviceCapabilities) {
+ ptr->dev_capability[index] = malloc(dlen);
+ if (ptr->dev_capability[index] == NULL) {
+ libusb_free_bos_descriptor(ptr);
+ return LIBUSB_ERROR_NO_MEM;
+ }
+ memcpy(ptr->dev_capability[index], buf, dlen);
+ index++;
+ }
switch (((const uint8_t *)buf)[2]) {
case LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY:
if (ptr->usb_2_0_ext_cap != NULL || dcap_20 == NULL)
@@ -523,8 +539,11 @@ libusb_parse_bos_descriptor(const void *buf, int len,
buf = ((const uint8_t *)buf) + dlen;
len -= dlen;
}
- if (ptr != NULL)
+
+ if (ptr != NULL) {
+ ptr->bNumDeviceCapabilities = index;
return (0); /* success */
+ }
return (LIBUSB_ERROR_IO);
}
@@ -532,9 +551,14 @@ libusb_parse_bos_descriptor(const void *buf, int len,
void
libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos)
{
+ uint8_t i;
+
if (bos == NULL)
return;
+ for (i = 0; i != bos->bNumDeviceCapabilities; i++)
+ free(bos->dev_capability[i]);
+ free(bos->dev_capability);
free(bos);
}
OpenPOWER on IntegriCloud