Skip to content

Commit 4e63d6d

Browse files
authored
Introduce HID_API_MAX_REPORT_DESCRIPTOR_SIZE (signal11#452)
- first step is to use HID_API_MAX_REPORT_DESCRIPTOR_SIZE internally; - port a few improvements from get-descriptor branch early; Resolves: signal11#384
1 parent f45df3b commit 4e63d6d

File tree

4 files changed

+54
-69
lines changed

4 files changed

+54
-69
lines changed

hidapi/hidapi.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@
8888
*/
8989
#define HID_API_VERSION_STR HID_API_TO_VERSION_STR(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH)
9090

91+
/** @brief Maximum expected HID Report descriptor size in bytes.
92+
93+
Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0)
94+
95+
@ingroup API
96+
*/
97+
#define HID_API_MAX_REPORT_DESCRIPTOR_SIZE 4096
98+
9199
#ifdef __cplusplus
92100
extern "C" {
93101
#endif

libusb/hid.c

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -564,28 +564,43 @@ int HID_API_EXPORT hid_exit(void)
564564
return 0;
565565
}
566566

567-
/**
568-
* Requires an opened device with *claimed interface*.
569-
*/
570-
static void fill_device_info_usage(struct hid_device_info *cur_dev, libusb_device_handle *handle, int interface_num, uint16_t report_descriptor_size)
567+
static int hid_get_report_descriptor_libusb(libusb_device_handle *handle, int interface_num, uint16_t expected_report_descriptor_size, unsigned char *buf, size_t buf_size)
571568
{
572-
unsigned char data[4096];
573-
unsigned short page = 0, usage = 0;
569+
unsigned char tmp[HID_API_MAX_REPORT_DESCRIPTOR_SIZE];
574570

575-
if (report_descriptor_size > 4096)
576-
report_descriptor_size = 4096;
571+
if (expected_report_descriptor_size > HID_API_MAX_REPORT_DESCRIPTOR_SIZE)
572+
expected_report_descriptor_size = HID_API_MAX_REPORT_DESCRIPTOR_SIZE;
577573

578574
/* Get the HID Report Descriptor.
579575
See USB HID Specificatin, sectin 7.1.1
580576
*/
581-
int res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8), interface_num, data, report_descriptor_size, 5000);
577+
int res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8), interface_num, tmp, expected_report_descriptor_size, 5000);
578+
if (res < 0) {
579+
LOG("libusb_control_transfer() for getting the HID Report descriptor failed with %d: %s\n", res, libusb_error_name(res));
580+
return -1;
581+
}
582+
583+
if (res > (int)buf_size)
584+
res = (int)buf_size;
585+
586+
memcpy(buf, tmp, (size_t)res);
587+
return res;
588+
}
589+
590+
/**
591+
* Requires an opened device with *claimed interface*.
592+
*/
593+
static void fill_device_info_usage(struct hid_device_info *cur_dev, libusb_device_handle *handle, int interface_num, uint16_t expected_report_descriptor_size)
594+
{
595+
unsigned char hid_report_descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE];
596+
unsigned short page = 0, usage = 0;
597+
598+
int res = hid_get_report_descriptor_libusb(handle, interface_num, expected_report_descriptor_size, hid_report_descriptor, sizeof(hid_report_descriptor));
582599
if (res >= 0) {
583600
/* Parse the usage and usage page
584601
out of the report descriptor. */
585-
get_usage(data, res, &page, &usage);
602+
get_usage(hid_report_descriptor, res, &page, &usage);
586603
}
587-
else
588-
LOG("libusb_control_transfer() for getting the HID report descriptor failed with %d: %s\n", res, libusb_error_name(res));
589604

590605
cur_dev->usage_page = page;
591606
cur_dev->usage = usage;
@@ -619,7 +634,7 @@ static void invasive_fill_device_info_usage(struct hid_device_info *cur_dev, lib
619634
LOG("Can't release the interface.\n");
620635
}
621636
else
622-
LOG("Can't claim interface %d\n", res);
637+
LOG("Can't claim interface: (%d) %s\n", res, libusb_error_name(res));
623638

624639
#ifdef DETACH_KERNEL_DRIVER
625640
/* Re-attach kernel driver if necessary. */
@@ -675,7 +690,7 @@ static uint16_t get_report_descriptor_size_from_interface_descriptors(const stru
675690
{
676691
int i = 0;
677692
int found_hid_report_descriptor = 0;
678-
uint16_t result = 4096;
693+
uint16_t result = HID_API_MAX_REPORT_DESCRIPTOR_SIZE;
679694
const unsigned char *extra = intf_desc->extra;
680695
int extra_length = intf_desc->extra_length;
681696

@@ -943,7 +958,7 @@ static void read_callback(struct libusb_transfer *transfer)
943958
/* Re-submit the transfer object. */
944959
res = libusb_submit_transfer(transfer);
945960
if (res != 0) {
946-
LOG("Unable to submit URB. libusb error code: %d\n", res);
961+
LOG("Unable to submit URB: (%d) %s\n", res, libusb_error_name(res));
947962
dev->shutdown_thread = 1;
948963
dev->transfer_loop_finished = 1;
949964
}
@@ -981,7 +996,7 @@ static void *read_thread(void *param)
981996
res = libusb_handle_events(usb_context);
982997
if (res < 0) {
983998
/* There was an error. */
984-
LOG("read_thread(): libusb reports error # %d\n", res);
999+
LOG("read_thread(): (%d) %s\n", res, libusb_error_name(res));
9851000

9861001
/* Break out of this loop only on fatal error.*/
9871002
if (res != LIBUSB_ERROR_BUSY &&
@@ -1036,7 +1051,7 @@ static int hidapi_initialize_device(hid_device *dev, int config_number, const st
10361051
if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) {
10371052
res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber);
10381053
if (res < 0) {
1039-
LOG("Unable to detach Kernel Driver\n");
1054+
LOG("Unable to detach Kernel Driver: (%d) %s\n", res, libusb_error_name(res));
10401055
return 0;
10411056
}
10421057
else {
@@ -1047,13 +1062,13 @@ static int hidapi_initialize_device(hid_device *dev, int config_number, const st
10471062
#endif
10481063
res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber);
10491064
if (res < 0) {
1050-
LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res);
1065+
LOG("can't claim interface %d: (%d) %s\n", intf_desc->bInterfaceNumber, res, libusb_error_name(res));
10511066

10521067
#ifdef DETACH_KERNEL_DRIVER
10531068
if (dev->is_driver_detached) {
10541069
res = libusb_attach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber);
10551070
if (res < 0)
1056-
LOG("Failed to reattach the driver to kernel.\n");
1071+
LOG("Failed to reattach the driver to kernel: (%d) %s\n", res, libusb_error_name(res));
10571072
}
10581073
#endif
10591074
return 0;

linux/hid.c

Lines changed: 12 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@
7171
struct hid_device_ {
7272
int device_handle;
7373
int blocking;
74-
int uses_numbered_reports;
7574
wchar_t *last_error_str;
7675
struct hid_device_info* device_info;
7776
};
@@ -88,9 +87,12 @@ static wchar_t *last_global_error_str = NULL;
8887
static hid_device *new_hid_device(void)
8988
{
9089
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
90+
if (dev == NULL) {
91+
return NULL;
92+
}
93+
9194
dev->device_handle = -1;
9295
dev->blocking = 1;
93-
dev->uses_numbered_reports = 0;
9496
dev->last_error_str = NULL;
9597
dev->device_info = NULL;
9698

@@ -242,34 +244,6 @@ static int get_hid_item_size(__u8 *report_descriptor, unsigned int pos, __u32 si
242244
return 0;
243245
}
244246

245-
/* uses_numbered_reports() returns 1 if report_descriptor describes a device
246-
which contains numbered reports. */
247-
static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) {
248-
unsigned int i = 0;
249-
int data_len, key_size;
250-
251-
while (i < size) {
252-
int key = report_descriptor[i];
253-
254-
/* Check for the Report ID key */
255-
if (key == 0x85/*Report ID*/) {
256-
/* This device has a Report ID, which means it uses
257-
numbered reports. */
258-
return 1;
259-
}
260-
261-
/* Determine data_len and key_size */
262-
if (!get_hid_item_size(report_descriptor, i, size, &data_len, &key_size))
263-
return 0; /* malformed report */
264-
265-
/* Skip over this key and its associated data */
266-
i += data_len + key_size;
267-
}
268-
269-
/* Didn't find a Report ID key. Device doesn't use numbered reports. */
270-
return 0;
271-
}
272-
273247
/*
274248
* Get bytes from a HID Report Descriptor.
275249
* Only call with a num_bytes of 0, 1, 2, or 4.
@@ -988,32 +962,22 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path)
988962
/* register_global_error: global error is reset by hid_init */
989963

990964
dev = new_hid_device();
965+
if (!dev) {
966+
register_global_error("Couldn't allocate memory");
967+
return NULL;
968+
}
991969

992970
dev->device_handle = open(path, O_RDWR | O_CLOEXEC);
993971

994-
/* If we have a good handle, return it. */
995972
if (dev->device_handle >= 0) {
996-
/* Get the report descriptor */
997973
int res, desc_size = 0;
998-
struct hidraw_report_descriptor rpt_desc;
999-
1000-
memset(&rpt_desc, 0x0, sizeof(rpt_desc));
1001974

1002-
/* Get Report Descriptor Size */
975+
/* Make sure this is a HIDRAW device - responds to HIDIOCGRDESCSIZE */
1003976
res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size);
1004-
if (res < 0)
1005-
register_device_error_format(dev, "ioctl (GRDESCSIZE): %s", strerror(errno));
1006-
1007-
/* Get Report Descriptor */
1008-
rpt_desc.size = desc_size;
1009-
res = ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc);
1010977
if (res < 0) {
1011-
register_device_error_format(dev, "ioctl (GRDESC): %s", strerror(errno));
1012-
} else {
1013-
/* Determine if this device uses numbered reports. */
1014-
dev->uses_numbered_reports =
1015-
uses_numbered_reports(rpt_desc.value,
1016-
rpt_desc.size);
978+
hid_close(dev);
979+
register_device_error_format(dev, "ioctl(GRDESCSIZE) error for '%s', not a HIDRAW device?: %s", path, strerror(errno));
980+
return NULL;
1017981
}
1018982

1019983
return dev;

mac/hid.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ struct hid_device_ {
124124
IOHIDDeviceRef device_handle;
125125
IOOptionBits open_options;
126126
int blocking;
127-
int uses_numbered_reports;
128127
int disconnected;
129128
CFStringRef run_loop_mode;
130129
CFRunLoopRef run_loop;
@@ -148,7 +147,6 @@ static hid_device *new_hid_device(void)
148147
dev->device_handle = NULL;
149148
dev->open_options = device_open_options;
150149
dev->blocking = 1;
151-
dev->uses_numbered_reports = 0;
152150
dev->disconnected = 0;
153151
dev->run_loop_mode = NULL;
154152
dev->run_loop = NULL;

0 commit comments

Comments
 (0)