Page MenuHomeFreeBSD

D50958.id157396.diff
No OneTemporary

D50958.id157396.diff

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

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)

Event Timeline