Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144725543
D50958.id160288.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D50958.id160288.diff
View Options
diff --git a/lib/libusb/libusb.h b/lib/libusb/libusb.h
--- a/lib/libusb/libusb.h
+++ b/lib/libusb/libusb.h
@@ -76,6 +76,7 @@
LIBUSB_DT_STRING = 0x03,
LIBUSB_DT_INTERFACE = 0x04,
LIBUSB_DT_ENDPOINT = 0x05,
+ LIBUSB_DT_INTERFACE_ASSOCIATION = 0x0b,
LIBUSB_DT_HID = 0x21,
LIBUSB_DT_REPORT = 0x22,
LIBUSB_DT_PHYSICAL = 0x23,
@@ -100,6 +101,7 @@
#define LIBUSB_DT_HUB_NONVAR_SIZE 7
#define LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE 6
#define LIBUSB_DT_BOS_SIZE 5
+#define LIBUSB_DT_INTERFACE_ASSOCIATION_SIZE 8
#define LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE 7
#define LIBUSB_SS_USB_DEVICE_CAPABILITY_SIZE 10
@@ -274,6 +276,8 @@
struct libusb_device_handle;
struct libusb_hotplug_callback_handle_struct;
+typedef struct libusb_context libusb_context;
+
struct libusb_pollfd {
int fd;
short events;
@@ -341,6 +345,22 @@
uint16_t wBytesPerInterval;
} libusb_ss_endpoint_companion_descriptor __aligned(sizeof(void *));
+typedef struct libusb_interface_association_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bFirstInterface;
+ uint8_t bInterfaceCount;
+ uint8_t bFunctionClass;
+ uint8_t bFunctionSubClass;
+ uint8_t bFunctionProtocol;
+ uint8_t iFunction;
+} libusb_interface_association_descriptor __aligned(sizeof(void *));
+
+struct libusb_interface_association_descriptor_array {
+ const struct libusb_interface_association_descriptor *iad;
+ int length;
+};
+
typedef struct libusb_interface_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
@@ -541,6 +561,9 @@
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_interface_association_descriptors(libusb_device *dev, uint8_t config_index, struct libusb_interface_association_descriptor_array **iad_arr);
+int libusb_get_active_interface_association_descriptors(libusb_device *dev, struct libusb_interface_association_descriptor_array **iad_arr);
+void libusb_free_interface_association_descriptors(struct libusb_interface_association_descriptor_array *iad_arr);
/* Asynchronous device I/O */
diff --git a/lib/libusb/libusb.3 b/lib/libusb/libusb.3
--- a/lib/libusb/libusb.3
+++ b/lib/libusb/libusb.3
@@ -536,6 +536,33 @@
.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_interface_association_descriptors "libusb_device *dev" "uint8_t config_index" "struct libusb_interface_association_descriptor_array **iad_arr"
+This function parses the interface association descriptor from the descriptor given by
+.Fa dev
+and
+.Fa config_index
+then stores a pointer to the parsed descriptor into
+.Fa iad_array.
+Return zero on success and a LIBUSB_ERROR code on failure.
+On success the parsed interface association descriptor must be freed using the
+libusb_free_interface_association_descriptors function.
+.Pp
+.Ft int
+.Fn libusb_get_active_interface_association_descriptors "libusb_device *dev" "struct libusb_interface_association_descriptor_array **iad_arr"
+This function parses the interface association descriptor from the descriptor given by
+.Fa dev
+and active config then stores a pointer to the parsed descriptor into
+.Fa iad_array.
+Return zero on success and a LIBUSB_ERROR code on failure.
+On success the parsed interface association descriptor must be freed using the
+libusb_free_interface_association_descriptors function.
+.Pp
+.Ft void
+.Fn libusb_free_interface_association_descriptors "struct libusb_interface_association_descriptor_array *iad_arr"
+This function is NULL safe and frees a parsed interface association ID descriptor given by
+.Fa desc .
.Sh USB ASYNCHRONOUS I/O
.Ft struct libusb_transfer *
.Fn libusb_alloc_transfer "int iso_packets"
diff --git a/lib/libusb/libusb10_desc.c b/lib/libusb/libusb10_desc.c
--- a/lib/libusb/libusb10_desc.c
+++ b/lib/libusb/libusb10_desc.c
@@ -714,3 +714,91 @@
free(container_id);
}
+
+int
+libusb_get_interface_association_descriptors(libusb_device *dev,
+ uint8_t config_index,
+ struct libusb_interface_association_descriptor_array **iad_arr)
+{
+ struct libusb_interface_association_descriptor_array *iads;
+ struct libusb_interface_association_descriptor *iad;
+ struct libusb20_config *config;
+ struct LIBUSB20_INTERFACE_ASSOCIATION_DESC_DECODED *iad_desc;
+
+ int idx;
+ int niad;
+
+ if (!iad_arr)
+ return (LIBUSB_ERROR_INVALID_PARAM);
+
+ if (config_index >= dev->os_priv->ddesc.bNumConfigurations)
+ return (LIBUSB_ERROR_NOT_FOUND);
+
+ config = libusb20_dev_alloc_config(dev->os_priv, config_index);
+ if (config == NULL)
+ return (LIBUSB_ERROR_NO_MEM);
+ niad = config->niad;
+ if (niad == 0) {
+ free(config);
+ return (0);
+ }
+
+ iads = calloc(sizeof(
+ struct libusb_interface_association_descriptor_array),
+ 1);
+ if (iads == NULL) {
+ free(config);
+ return (LIBUSB_ERROR_NO_MEM);
+ }
+ *iad_arr = iads;
+
+ iad = malloc(
+ sizeof(struct libusb_interface_association_descriptor) * niad);
+ if (iad == NULL) {
+ free(iads);
+ free(config);
+ return (LIBUSB_ERROR_NO_MEM);
+ }
+
+ for (idx = 0; idx < niad; ++idx) {
+ iad_desc = &config->iad_desc[idx].desc;
+ iad[idx].bLength = iad_desc->bLength;
+ iad[idx].bDescriptorType = iad_desc->bDescriptorType;
+ iad[idx].bFirstInterface = iad_desc->bFirstInterface;
+ iad[idx].bInterfaceCount = iad_desc->bInterfaceCount;
+ iad[idx].bFunctionClass = iad_desc->bFunctionClass;
+ iad[idx].bFunctionSubClass = iad_desc->bFunctionSubClass;
+ iad[idx].bFunctionProtocol = iad_desc->bFunctionProtocol;
+ iad[idx].iFunction = iad_desc->iFunction;
+ }
+ iads->length = niad;
+ iads->iad = iad;
+
+ free(config);
+ return (0);
+}
+
+int
+libusb_get_active_interface_association_descriptors(libusb_device *dev,
+ struct libusb_interface_association_descriptor_array **iad_arr)
+{
+ struct libusb20_device *pdev;
+ uint8_t config_index;
+
+ pdev = dev->os_priv;
+ config_index = libusb20_dev_get_config_index(pdev);
+
+ return (libusb_get_interface_association_descriptors(dev, config_index,
+ iad_arr));
+}
+
+void
+libusb_free_interface_association_descriptors(
+ struct libusb_interface_association_descriptor_array *iad_arr)
+{
+ if (iad_arr == NULL)
+ return;
+ if (iad_arr->iad)
+ free((void *)iad_arr->iad);
+ free(iad_arr);
+}
diff --git a/lib/libusb/libusb20_desc.h b/lib/libusb/libusb20_desc.h
--- a/lib/libusb/libusb20_desc.h
+++ b/lib/libusb/libusb20_desc.h
@@ -248,6 +248,19 @@
LIBUSB20_MAKE_STRUCT(LIBUSB20_INTERFACE_DESC);
+#define LIBUSB20_INTERFACE_ASSOCIATION_DESC(m,n) \
+ m(n, UINT8_T, bLength, ) \
+ m(n, UINT8_T, bDescriptorType, ) \
+ m(n, UINT8_T, bFirstInterface, ) \
+ m(n, UINT8_T, bInterfaceCount, ) \
+ m(n, UINT8_T, bFunctionClass, ) \
+ m(n, UINT8_T, bFunctionSubClass, ) \
+ m(n, UINT8_T, bFunctionProtocol, ) \
+ m(n, UINT8_T, bInterfaceProtocol, ) \
+ m(n, UINT8_T, iFunction, ) \
+
+LIBUSB20_MAKE_STRUCT(LIBUSB20_INTERFACE_ASSOCIATION_DESC);
+
#define LIBUSB20_CONFIG_DESC(m,n) \
m(n, UINT8_T, bLength, ) \
m(n, UINT8_T, bDescriptorType, ) \
@@ -368,6 +381,10 @@
/** Endpoint descriptor. See LIBUSB20_ENDPOINT_DESC. */
LIBUSB20_DT_ENDPOINT = 0x05,
+ /** Interface Association descriptor. See
+ LIBUSB20_INTERFACE_ASSOCIATION_DESC. */
+ LIBUSB20_DT_INTERFACE_ASSOCIATION = 0x0b,
+
/** HID descriptor */
LIBUSB20_DT_HID = 0x21,
@@ -583,11 +600,18 @@
uint8_t num_endpoints;
} __aligned(sizeof(void *));
+struct libusb20_iad_desc {
+ struct LIBUSB20_INTERFACE_ASSOCIATION_DESC_DECODED desc;
+ struct libusb20_me_struct extra;
+} __aligned(sizeof(void *));
+
struct libusb20_config {
struct LIBUSB20_CONFIG_DESC_DECODED desc;
struct libusb20_me_struct extra;
struct libusb20_interface *interface;
uint8_t num_interface;
+ struct libusb20_iad_desc *iad_desc;
+ int niad;
} __aligned(sizeof(void *));
uint8_t libusb20_me_get_1(const struct libusb20_me_struct *ie, uint16_t offset);
diff --git a/lib/libusb/libusb20_desc.c b/lib/libusb/libusb20_desc.c
--- a/lib/libusb/libusb20_desc.c
+++ b/lib/libusb/libusb20_desc.c
@@ -44,6 +44,7 @@
LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_DEVICE_DESC);
LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_ENDPOINT_DESC);
LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_INTERFACE_DESC);
+LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_INTERFACE_ASSOCIATION_DESC);
LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_CONFIG_DESC);
LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_CONTROL_SETUP);
LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_SS_ENDPT_COMP_DESC);
@@ -67,12 +68,15 @@
struct libusb20_interface *last_if;
struct libusb20_endpoint *lub_endpoint;
struct libusb20_endpoint *last_ep;
+ struct libusb20_iad_desc *last_iad;
+ struct libusb20_iad_desc *lub_iad;
struct libusb20_me_struct pcdesc;
const uint8_t *ptr;
uint32_t size;
uint16_t niface_no_alt;
uint16_t niface;
+ uint16_t niad;
uint16_t nendpoint;
uint16_t iface_no;
@@ -89,6 +93,7 @@
nendpoint = 0;
niface = 0;
iface_no = 0xFFFF;
+ niad = 0;
ptr = NULL;
/* get "wTotalLength" and setup "pcdesc" */
@@ -109,6 +114,8 @@
iface_no = ptr[2];
niface_no_alt++;
}
+ } else if (ptr[1] == LIBUSB20_DT_INTERFACE_ASSOCIATION) {
+ niad++;
}
}
@@ -119,10 +126,12 @@
if (nendpoint >= 256) {
return (NULL); /* corrupt */
}
- size = sizeof(*lub_config) +
- (niface * sizeof(*lub_interface)) +
+ if (niad >= 256)
+ return (NULL);
+
+ size = sizeof(*lub_config) + (niface * sizeof(*lub_interface)) +
(nendpoint * sizeof(*lub_endpoint)) +
- pcdesc.len;
+ (niad * sizeof(*lub_iad)) + pcdesc.len;
lub_config = malloc(size);
if (lub_config == NULL) {
@@ -134,14 +143,15 @@
lub_interface = (void *)(lub_config + 1);
lub_alt_interface = (void *)(lub_interface + niface_no_alt);
lub_endpoint = (void *)(lub_interface + niface);
+ lub_iad = (void *)(lub_endpoint + nendpoint);
/*
* Make a copy of the config descriptor, so that the caller can free
* the initial config descriptor pointer!
*/
- memcpy((void *)(lub_endpoint + nendpoint), config_desc, pcdesc.len);
+ memcpy((void *)(lub_iad + niad), config_desc, pcdesc.len);
- ptr = (const void *)(lub_endpoint + nendpoint);
+ ptr = (const void *)(lub_iad + niad);
pcdesc.ptr = LIBUSB20_ADD_BYTES(ptr, 0);
/* init config structure */
@@ -156,6 +166,8 @@
lub_config->extra.ptr = LIBUSB20_ADD_BYTES(ptr, ptr[0]);
lub_config->extra.len = -ptr[0];
lub_config->extra.type = LIBUSB20_ME_IS_RAW;
+ lub_config->niad = niad;
+ lub_config->iad_desc = lub_iad;
/* reset states */
niface = 0;
@@ -163,8 +175,10 @@
ptr = NULL;
lub_interface--;
lub_endpoint--;
+ lub_iad--;
last_if = NULL;
last_ep = NULL;
+ last_iad = NULL;
/* descriptor pre-scan */
while ((ptr = libusb20_desc_foreach(&pcdesc, ptr))) {
@@ -223,6 +237,15 @@
last_if->num_altsetting = 0;
last_if->num_endpoints = 0;
last_ep = NULL;
+ } else if (ptr[1] == LIBUSB20_DT_INTERFACE_ASSOCIATION) {
+ lub_iad++;
+ last_iad = lub_iad;
+ LIBUSB20_INIT(LIBUSB20_INTERFACE_ASSOCIATION_DESC,
+ &last_iad->desc);
+ libusb20_me_decode(ptr, ptr[0], &last_iad->desc);
+ last_iad->extra.ptr = LIBUSB20_ADD_BYTES(ptr, ptr[0]);
+ last_iad->extra.len = 0;
+ last_iad->extra.type = LIBUSB20_ME_IS_RAW;
} else {
/* unknown descriptor */
if (last_if) {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Feb 12, 5:50 PM (18 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28668970
Default Alt Text
D50958.id160288.diff (11 KB)
Attached To
Mode
D50958: libusb: add parser for interface association descriptor
Attached
Detach File
Event Timeline
Log In to Comment