Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142115887
D50958.id157396.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.id157396.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,11 +76,12 @@
LIBUSB_DT_STRING = 0x03,
LIBUSB_DT_INTERFACE = 0x04,
LIBUSB_DT_ENDPOINT = 0x05,
+ LIBUSB_DT_BOS = 0x0f,
+ LIBUSB_DT_INTERFACE_ASSOCIATION = 0x0b,
LIBUSB_DT_HID = 0x21,
LIBUSB_DT_REPORT = 0x22,
LIBUSB_DT_PHYSICAL = 0x23,
LIBUSB_DT_HUB = 0x29,
- LIBUSB_DT_BOS = 0x0f,
LIBUSB_DT_DEVICE_CAPABILITY = 0x10,
LIBUSB_DT_SS_ENDPOINT_COMPANION = 0x30,
};
@@ -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
@@ -271,6 +273,8 @@
struct libusb_device_handle;
struct libusb_hotplug_callback_handle_struct;
+typedef struct libusb_context libusb_context;
+
struct libusb_pollfd {
int fd;
short events;
@@ -338,6 +342,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;
@@ -544,7 +564,9 @@
uint8_t *libusb_control_transfer_get_data(struct libusb_transfer *transfer);
struct libusb_control_setup *libusb_control_transfer_get_setup(struct libusb_transfer *transfer);
void libusb_fill_control_setup(uint8_t *buf, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength);
-void libusb_fill_control_transfer(struct libusb_transfer *transfer, libusb_device_handle *devh, uint8_t *buf, libusb_transfer_cb_fn callback, void *user_data, uint32_t timeout);
+void libusb_fill_control_transfer(struct libusb_transfer *transfer,
+ libusb_device_handle *dev, uint8_t *buf, libusb_transfer_cb_fn callback,
+ void *user_data, uint32_t timeout);
void libusb_fill_bulk_transfer(struct libusb_transfer *transfer, libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, int length, libusb_transfer_cb_fn callback, void *user_data, uint32_t timeout);
void libusb_fill_interrupt_transfer(struct libusb_transfer *transfer, libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, int length, libusb_transfer_cb_fn callback, void *user_data, uint32_t timeout);
void libusb_fill_iso_transfer(struct libusb_transfer *transfer, libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, int length, int npacket, libusb_transfer_cb_fn callback, void *user_data, uint32_t timeout);
@@ -594,8 +616,13 @@
int libusb_free_streams(libusb_device_handle *dev, unsigned char *endpoints, int num_endpoints);
void libusb_transfer_set_stream_id(struct libusb_transfer *transfer, uint32_t stream_id);
uint32_t libusb_transfer_get_stream_id(struct libusb_transfer *transfer);
-
+int libusb_get_interface_association_descriptors(libusb_device *dev,
+ uint8_t config_index,
+ struct libusb_interface_association_descriptor_array **iad_array);
+void libusb_free_interface_association_descriptors(
+ struct libusb_interface_association_descriptor_array *);
#if 0
+
{ /* indent fix */
#endif
#ifdef __cplusplus
diff --git a/lib/libusb/libusb.3 b/lib/libusb/libusb.3
--- a/lib/libusb/libusb.3
+++ b/lib/libusb/libusb.3
@@ -506,6 +506,21 @@
.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_array"
+This function parse the interface association descriptor from the descriptor given by
+.Fa dev
+and 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 *desc"
+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
@@ -713,3 +713,68 @@
free(container_id);
}
+
+int
+libusb_get_interface_association_descriptors(libusb_device *dev,
+ uint8_t config_index,
+ struct libusb_interface_association_descriptor_array **iad_array)
+{
+ 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_array)
+ 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;
+
+ iads = calloc(sizeof(
+ struct libusb_interface_association_descriptor_array),
+ 1);
+ if (iads == NULL)
+ return (LIBUSB_ERROR_NO_MEM);
+ *iad_array = iads;
+ if (niad == 0)
+ return (0);
+
+ iad = malloc(
+ sizeof(struct libusb_interface_association_descriptor) * niad);
+ if (iad == NULL)
+ 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);
+}
+
+void
+libusb_free_interface_association_descriptors(
+ struct libusb_interface_association_descriptor_array *desc)
+{
+ if (desc->iad)
+ free((void *)desc->iad);
+ free(desc);
+}
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, UINT16_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, ) \
@@ -364,6 +377,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,
@@ -579,11 +596,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;
+ struct libusb20_iad_desc *iad_desc;
uint8_t num_interface;
+ struct libusb20_interface *interface;
+ 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
Sat, Jan 17, 4:05 AM (13 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27680166
Default Alt Text
D50958.id157396.diff (11 KB)
Attached To
Mode
D50958: libusb: add parser for interface association descriptor
Attached
Detach File
Event Timeline
Log In to Comment