summaryrefslogtreecommitdiff
path: root/lib/iface_list.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/iface_list.c')
-rw-r--r--lib/iface_list.c57
1 files changed, 50 insertions, 7 deletions
diff --git a/lib/iface_list.c b/lib/iface_list.c
index 1b028b1..bd208aa 100644
--- a/lib/iface_list.c
+++ b/lib/iface_list.c
@@ -27,6 +27,7 @@
#include "config.h"
#include "uhd/iface_list.h"
+#include "uhd/misc.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
@@ -76,6 +77,10 @@ uhd_iface_list_new(uhd_dev *dev_list,
uhd_dev *dev;
struct libusb_config_descriptor *config = NULL;
const struct libusb_interface *lusb_iface;
+ const struct libusb_interface_descriptor *iface_desc;
+ const uhd_hid_descriptor *hid_desc;
+ const uhd_hid_descriptor_extra *hid_desc_extra;
+ uint16_t rd_len;
const struct libusb_endpoint_descriptor *ep_list;
uint8_t ep_num;
const struct libusb_endpoint_descriptor *ep;
@@ -101,14 +106,51 @@ uhd_iface_list_new(uhd_dev *dev_list,
lusb_iface - config->interface < config->bNumInterfaces;
lusb_iface++)
{
- /* Skip interfaces with altsettings and non-HID interfaces */
- if (lusb_iface->num_altsetting != 1 ||
- lusb_iface->altsetting->bInterfaceClass != LIBUSB_CLASS_HID)
+ /* Skip interfaces with altsettings */
+ if (lusb_iface->num_altsetting != 1)
continue;
+ iface_desc = lusb_iface->altsetting;
+
+ /* Skip non-HID interfaces */
+ if (iface_desc->bInterfaceClass != LIBUSB_CLASS_HID)
+ continue;
+
+ /*
+ * Try to retrieve report descriptor length
+ */
+ rd_len = UHD_MAX_DESCRIPTOR_SIZE;
+ /* If interface descriptor has space for a HID descriptor */
+ if (iface_desc->extra_length >= (int)sizeof(uhd_hid_descriptor))
+ {
+ hid_desc = (const uhd_hid_descriptor *)iface_desc->extra;
+ /* If this is truly a HID class descriptor */
+ if (hid_desc->bDescriptorType == LIBUSB_DT_HID)
+ {
+ /* For each extra HID descriptor entry */
+ for (hid_desc_extra = hid_desc->extra;
+ hid_desc_extra <
+ hid_desc->extra + hid_desc->bNumDescriptors &&
+ (uint8_t *)hid_desc_extra <
+ (uint8_t *)hid_desc + hid_desc->bLength &&
+ (unsigned char *)hid_desc_extra <
+ iface_desc->extra +
+ iface_desc->extra_length;
+ hid_desc_extra++) {
+ /* If this is a report descriptor entry */
+ if (hid_desc_extra->bDescriptorType ==
+ LIBUSB_DT_REPORT)
+ {
+ rd_len = hid_desc_extra->wDescriptorLength;
+ break;
+ }
+ }
+ }
+ }
+
/* Retrieve endpoint list */
- ep_list = lusb_iface->altsetting->endpoint;
- ep_num = lusb_iface->altsetting->bNumEndpoints;
+ ep_list = iface_desc->endpoint;
+ ep_num = iface_desc->bNumEndpoints;
/* For each endpoint */
for (ep = ep_list; (ep - ep_list) < ep_num; ep++)
@@ -123,8 +165,9 @@ uhd_iface_list_new(uhd_dev *dev_list,
/* Create the interface */
iface = uhd_iface_new(
dev,
- lusb_iface->altsetting->bInterfaceNumber,
- ep->bEndpointAddress, ep->wMaxPacketSize);
+ iface_desc->bInterfaceNumber,
+ ep->bEndpointAddress, ep->wMaxPacketSize,
+ rd_len);
if (iface == NULL)
{
err = LIBUSB_ERROR_NO_MEM;