From 566a620b3f6dd3e528d1c4a89eb9f6cdb52e86f9 Mon Sep 17 00:00:00 2001 From: Daniel Van Noord Date: Thu, 1 Aug 2019 11:22:17 -0400 Subject: [PATCH 01/12] Added support for Get Input Report to linux, mac, windows and libusb. --- hidapi/hidapi.h | 25 +++++++++++++++++++++++++ libusb/hid.c | 29 +++++++++++++++++++++++++++++ linux/hid.c | 11 +++++++++++ mac/hid.c | 18 ++++++++++++++++++ windows/hid.c | 15 +++++++++++++++ 5 files changed, 98 insertions(+) diff --git a/hidapi/hidapi.h b/hidapi/hidapi.h index ca43bcd41..202195190 100644 --- a/hidapi/hidapi.h +++ b/hidapi/hidapi.h @@ -334,6 +334,31 @@ extern "C" { */ int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length); + /** @brief Get a input report from a HID device. + + Set the first byte of @p data[] to the Report ID of the + report to be read. Make sure to allow space for this + extra byte in @p data[]. Upon return, the first byte will + still contain the Report ID, and the report data will + start in data[1]. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into, including + the Report ID. Set the first byte of @p data[] to the + Report ID of the report to be read, or set it to zero + if your device does not use numbered reports. + @param length The number of bytes to read, including an + extra byte for the report ID. The buffer can be longer + than the actual report. + + @returns + This function returns the number of bytes read plus + one for the report ID (which is still in the first + byte), or -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length); + /** @brief Close a HID device. This function sets the return value of hid_error(). diff --git a/libusb/hid.c b/libusb/hid.c index 298793961..6a0b17bfc 100644 --- a/libusb/hid.c +++ b/libusb/hid.c @@ -1227,6 +1227,35 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, return res; } +int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) +{ + int res = -1; + int skipped_report_id = 0; + int report_number = data[0]; + + if (report_number == 0x0) { + /* Offset the return buffer by 1, so that the report ID + will remain in byte 0. */ + data++; + length--; + skipped_report_id = 1; + } + res = libusb_control_transfer(dev->device_handle, + LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN, + 0x01/*HID get_report*/, + (1/*HID Input*/ << 8) | report_number, + dev->interface, + (unsigned char *)data, length, + 1000/*timeout millis*/); + + if (res < 0) + return -1; + + if (skipped_report_id) + res++; + + return res; +} void HID_API_EXPORT hid_close(hid_device *dev) { diff --git a/linux/hid.c b/linux/hid.c index c8720dbf2..9d4410937 100644 --- a/linux/hid.c +++ b/linux/hid.c @@ -38,6 +38,7 @@ #include /* Linux */ +#include #include #include #include @@ -790,6 +791,16 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, return res; } +int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) +{ + int res; + + res = ioctl(dev->device_handle, HIDIOCGREPORT, data); + if (res < 0) + perror("ioctl (GINPUT)"); + + return res; +} void HID_API_EXPORT hid_close(hid_device *dev) { diff --git a/mac/hid.c b/mac/hid.c index 77308d189..20b75cf6b 100644 --- a/mac/hid.c +++ b/mac/hid.c @@ -971,6 +971,24 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, return -1; } +int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) +{ + CFIndex len = length; + IOReturn res; + + /* Return if the device has been unplugged. */ + if (dev->disconnected) + return -1; + + res = IOHIDDeviceGetReport(dev->device_handle, + kIOHIDReportTypeInput, + data[0], /* Report ID */ + data, &len); + if (res == kIOReturnSuccess) + return len; + else + return -1; +} void HID_API_EXPORT hid_close(hid_device *dev) { diff --git a/windows/hid.c b/windows/hid.c index c31af3087..f3c511df8 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -109,6 +109,7 @@ extern "C" { typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length); typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length); + typedef BOOLEAN(__stdcall *HidD_GetInputReport_)(HANDLE handle, PVOID data, ULONG length); typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len); typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data); typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data); @@ -121,6 +122,7 @@ extern "C" { static HidD_GetProductString_ HidD_GetProductString; static HidD_SetFeature_ HidD_SetFeature; static HidD_GetFeature_ HidD_GetFeature; + static HidD_GetInputReport_ HidD_GetInputReport; static HidD_GetIndexedString_ HidD_GetIndexedString; static HidD_GetPreparsedData_ HidD_GetPreparsedData; static HidD_FreePreparsedData_ HidD_FreePreparsedData; @@ -211,6 +213,7 @@ static int lookup_functions() RESOLVE(HidD_GetProductString); RESOLVE(HidD_SetFeature); RESOLVE(HidD_GetFeature); + RESOLVE(HidD_GetInputReport); RESOLVE(HidD_GetIndexedString); RESOLVE(HidD_GetPreparsedData); RESOLVE(HidD_FreePreparsedData); @@ -818,6 +821,18 @@ int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned #endif } + +int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) +{ + BOOL res; + res = HidD_GetInputReport(dev->device_handle, data, length); + if (!res) { + register_error(dev, "HidD_GetInputReport"); + return -1; + } + return length; +} + void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) { if (!dev) From 516f0108f2dfd5ef937be9c8a2627961ab5b2d90 Mon Sep 17 00:00:00 2001 From: Daniel Van Noord Date: Thu, 1 Aug 2019 13:37:22 -0400 Subject: [PATCH 02/12] Switched windows Get_Input_Report to use the same method as Get_Feature_Report so the returned length matches. --- windows/hid.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/windows/hid.c b/windows/hid.c index f3c511df8..6da04e6fc 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -55,6 +55,7 @@ extern "C" { #define HID_OUT_CTL_CODE(id) \ CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) #define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) + #define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104) #ifdef __cplusplus } /* extern "C" */ @@ -824,13 +825,50 @@ int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) { +#if 0 BOOL res; res = HidD_GetInputReport(dev->device_handle, data, length); if (!res) { register_error(dev, "HidD_GetInputReport"); return -1; } - return length; + return length +#else + DWORD bytes_returned; + + OVERLAPPED ol; + memset(&ol, 0, sizeof(ol)); + + BOOL res = DeviceIoControl(dev->device_handle, + IOCTL_HID_GET_INPUT_REPORT, + data, length, + data, length, + &bytes_returned, &ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* DeviceIoControl() failed. Return error. */ + register_error(dev, "Send Input Report DeviceIoControl"); + return -1; + } + } + + /* Wait here until the write is done. This makes + hid_get_feature_report() synchronous. */ + res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/); + if (!res) { + /* The operation failed. */ + register_error(dev, "Send Input Report GetOverLappedResult"); + return -1; + } + + /* bytes_returned does not include the first byte which contains the + report ID. The data buffer actually contains one more byte than + bytes_returned. */ + bytes_returned++; + + return bytes_returned; +#endif } void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) From aaa953b5c605cac7c724b0f29652f076219d78a7 Mon Sep 17 00:00:00 2001 From: Daniel Van Noord Date: Thu, 1 Aug 2019 13:38:00 -0400 Subject: [PATCH 03/12] Update hidapi/hidapi.h Co-Authored-By: Ihor Dutchak --- hidapi/hidapi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hidapi/hidapi.h b/hidapi/hidapi.h index 202195190..6487e60af 100644 --- a/hidapi/hidapi.h +++ b/hidapi/hidapi.h @@ -334,7 +334,7 @@ extern "C" { */ int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length); - /** @brief Get a input report from a HID device. + /** @brief Get a input report from a HID device. Set the first byte of @p data[] to the Report ID of the report to be read. Make sure to allow space for this From 80c3986ab110421482c7532478dfc99941e40ceb Mon Sep 17 00:00:00 2001 From: Daniel Van Noord Date: Thu, 1 Aug 2019 13:39:57 -0400 Subject: [PATCH 04/12] Changed to use the new error handler. --- linux/hid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/hid.c b/linux/hid.c index 9d4410937..56d99c77e 100644 --- a/linux/hid.c +++ b/linux/hid.c @@ -797,7 +797,7 @@ int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned c res = ioctl(dev->device_handle, HIDIOCGREPORT, data); if (res < 0) - perror("ioctl (GINPUT)"); + register_device_error_format(dev, "ioctl (GINPUT): %s", strerror(errno)); return res; } From 4fbd9a092b100ca1901e0de597542e0d8a2095d1 Mon Sep 17 00:00:00 2001 From: Daniel Van Noord Date: Thu, 1 Aug 2019 14:35:33 -0400 Subject: [PATCH 05/12] Fixed GINPUT to be GREPORT --- linux/hid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/hid.c b/linux/hid.c index 56d99c77e..c0d52c405 100644 --- a/linux/hid.c +++ b/linux/hid.c @@ -797,7 +797,7 @@ int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned c res = ioctl(dev->device_handle, HIDIOCGREPORT, data); if (res < 0) - register_device_error_format(dev, "ioctl (GINPUT): %s", strerror(errno)); + register_device_error_format(dev, "ioctl (GREPORT): %s", strerror(errno)); return res; } From 26378f93b75ce0958ba30049cf754ad8de6f72dd Mon Sep 17 00:00:00 2001 From: Daniel Van Noord Date: Thu, 1 Aug 2019 14:38:34 -0400 Subject: [PATCH 06/12] Fix for possible memory corruption in linux/hid.c get_input_report. --- linux/hid.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/linux/hid.c b/linux/hid.c index c0d52c405..801818c7b 100644 --- a/linux/hid.c +++ b/linux/hid.c @@ -795,10 +795,20 @@ int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned c { int res; - res = ioctl(dev->device_handle, HIDIOCGREPORT, data); + unsigned char bfr[64] = {0}; //Maximum Hid Report Size is 64 bytes, added one extra. See https://www.usb.org/sites/default/files/documents/hid1_11.pdf section 5.6 + + if(length > 64){ + register_device_error_format(dev, "ioctl (GREPORT): %s", strerror(EINVAL)); //22 /* Invalid argument */ + } + + memcpy(bfr, data, length); // copy the data onto the buffer + + res = ioctl(dev->device_handle, HIDIOCGREPORT, bfr); if (res < 0) register_device_error_format(dev, "ioctl (GREPORT): %s", strerror(errno)); + memcpy(data, bfr, length); + return res; } From ed85a3d9fa12a310ed79f7010115e176797a66ee Mon Sep 17 00:00:00 2001 From: Daniel Van Noord Date: Sat, 10 Aug 2019 20:15:30 -0400 Subject: [PATCH 07/12] Minor cleanup / formatting changes. --- hidapi/hidapi.h | 2 +- linux/hid.c | 1 - windows/hid.c | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/hidapi/hidapi.h b/hidapi/hidapi.h index 6487e60af..4102e6c17 100644 --- a/hidapi/hidapi.h +++ b/hidapi/hidapi.h @@ -337,7 +337,7 @@ extern "C" { /** @brief Get a input report from a HID device. Set the first byte of @p data[] to the Report ID of the - report to be read. Make sure to allow space for this + report to be read. Make sure to allow space for this extra byte in @p data[]. Upon return, the first byte will still contain the Report ID, and the report data will start in data[1]. diff --git a/linux/hid.c b/linux/hid.c index 801818c7b..91a587f83 100644 --- a/linux/hid.c +++ b/linux/hid.c @@ -794,7 +794,6 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) { int res; - unsigned char bfr[64] = {0}; //Maximum Hid Report Size is 64 bytes, added one extra. See https://www.usb.org/sites/default/files/documents/hid1_11.pdf section 5.6 if(length > 64){ diff --git a/windows/hid.c b/windows/hid.c index 6da04e6fc..413edcade 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -832,7 +832,7 @@ int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned c register_error(dev, "HidD_GetInputReport"); return -1; } - return length + return length; #else DWORD bytes_returned; From 9f75d4edf0e6b02931aabb63fc2550461e9f2892 Mon Sep 17 00:00:00 2001 From: Daniel Van Noord Date: Fri, 23 Aug 2019 19:01:08 -0400 Subject: [PATCH 08/12] Removed incorrect Linux implementation. --- linux/hid.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/linux/hid.c b/linux/hid.c index 91a587f83..418f6f5d9 100644 --- a/linux/hid.c +++ b/linux/hid.c @@ -791,24 +791,10 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, return res; } +//Not implemented for Linux HidRaw yet int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) { - int res; - unsigned char bfr[64] = {0}; //Maximum Hid Report Size is 64 bytes, added one extra. See https://www.usb.org/sites/default/files/documents/hid1_11.pdf section 5.6 - - if(length > 64){ - register_device_error_format(dev, "ioctl (GREPORT): %s", strerror(EINVAL)); //22 /* Invalid argument */ - } - - memcpy(bfr, data, length); // copy the data onto the buffer - - res = ioctl(dev->device_handle, HIDIOCGREPORT, bfr); - if (res < 0) - register_device_error_format(dev, "ioctl (GREPORT): %s", strerror(errno)); - - memcpy(data, bfr, length); - - return res; + return -1; } void HID_API_EXPORT hid_close(hid_device *dev) From 1fa49e88e491dff33b24ea5788aa6ae18af80b55 Mon Sep 17 00:00:00 2001 From: Daniel Van Noord Date: Sat, 24 Aug 2019 22:13:24 -0400 Subject: [PATCH 09/12] Update linux/hid.c Co-Authored-By: Ihor Dutchak --- linux/hid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/hid.c b/linux/hid.c index 418f6f5d9..86fb55166 100644 --- a/linux/hid.c +++ b/linux/hid.c @@ -791,7 +791,7 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, return res; } -//Not implemented for Linux HidRaw yet +// Not supported by Linux HidRaw yet int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) { return -1; From 6871817802bfa08027c9311fe83dc61051ff6b72 Mon Sep 17 00:00:00 2001 From: Daniel Van Noord Date: Fri, 27 Sep 2019 12:52:34 -0400 Subject: [PATCH 10/12] Updated mac to use new implementation --- mac/hid.c | 108 +++++++++++++++++++++++++++--------------------------- 1 file changed, 53 insertions(+), 55 deletions(-) diff --git a/mac/hid.c b/mac/hid.c index 20b75cf6b..6d7b372db 100644 --- a/mac/hid.c +++ b/mac/hid.c @@ -696,11 +696,11 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) io_registry_entry_t entry = MACH_PORT_NULL; IOReturn ret = kIOReturnInvalid; - dev = new_hid_device(); - /* Set up the HID Manager if it hasn't been done */ if (hid_init() < 0) - return NULL; + goto return_error; + + dev = new_hid_device(); /* Get the IORegistry entry for the given path */ entry = IORegistryEntryFromPath(kIOMasterPortDefault, path); @@ -763,38 +763,64 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char *data, size_t length) { - const unsigned char *data_to_send; - size_t length_to_send; + const unsigned char *data_to_send = data; + CFIndex length_to_send = length; IOReturn res; + const unsigned char report_id = data[0]; - /* Return if the device has been disconnected. */ - if (dev->disconnected) - return -1; - - if (data[0] == 0x0) { + if (report_id == 0x0) { /* Not using numbered Reports. Don't send the report number. */ data_to_send = data+1; length_to_send = length-1; } - else { - /* Using numbered Reports. - Send the Report Number */ - data_to_send = data; - length_to_send = length; + + /* Avoid crash if the device has been unplugged. */ + if (dev->disconnected) { + return -1; } - if (!dev->disconnected) { - res = IOHIDDeviceSetReport(dev->device_handle, - type, - data[0], /* Report ID*/ - data_to_send, length_to_send); + res = IOHIDDeviceSetReport(dev->device_handle, + type, + report_id, + data_to_send, length_to_send); + + if (res == kIOReturnSuccess) { + return length; + } + + return -1; +} + +static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data, size_t length) +{ + unsigned char *report = data; + CFIndex report_length = length; + IOReturn res = kIOReturnSuccess; + const unsigned char report_id = data[0]; + + if (report_id == 0x0) { + /* Not using numbered Reports. + Don't send the report number. */ + report = data+1; + report_length = length-1; + } + + /* Avoid crash if the device has been unplugged. */ + if (dev->disconnected) { + return -1; + } + + res = IOHIDDeviceGetReport(dev->device_handle, + type, + report_id, + report, &report_length); - if (res == kIOReturnSuccess) { - return length; + if (res == kIOReturnSuccess) { + if (report_id == 0x0) { // 0 report number still present at the beginning + report_length++; } - else - return -1; + return report_length; } return -1; @@ -954,40 +980,12 @@ int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) { - CFIndex len = length - 1; - IOReturn res; - - /* Return if the device has been unplugged. */ - if (dev->disconnected) - return -1; - - res = IOHIDDeviceGetReport(dev->device_handle, - kIOHIDReportTypeFeature, - data[0], /* Report ID */ - data + 1, &len); - if (res == kIOReturnSuccess) - return len + 1; - else - return -1; + return get_report(dev, kIOHIDReportTypeFeature, data, length); } int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) -{ - CFIndex len = length; - IOReturn res; - - /* Return if the device has been unplugged. */ - if (dev->disconnected) - return -1; - - res = IOHIDDeviceGetReport(dev->device_handle, - kIOHIDReportTypeInput, - data[0], /* Report ID */ - data, &len); - if (res == kIOReturnSuccess) - return len; - else - return -1; +{ + return get_report(dev, kIOHIDReportTypeInput, data, length); } void HID_API_EXPORT hid_close(hid_device *dev) From ab404ff50fa6dff4f7cab3e899fa7430ff5e8f8b Mon Sep 17 00:00:00 2001 From: Daniel Van Noord Date: Fri, 27 Sep 2019 13:02:29 -0400 Subject: [PATCH 11/12] Added hid_get_input_report to hidapi.def --- windows/ddk_build/hidapi.def | 1 + 1 file changed, 1 insertion(+) diff --git a/windows/ddk_build/hidapi.def b/windows/ddk_build/hidapi.def index 05e35afd6..01fe47d64 100644 --- a/windows/ddk_build/hidapi.def +++ b/windows/ddk_build/hidapi.def @@ -14,4 +14,5 @@ EXPORTS hid_open_path @12 hid_send_feature_report @13 hid_get_feature_report @14 + hid_get_input_report @15 \ No newline at end of file From f36bac02feb2bbe453b75387504137e0f9490d2f Mon Sep 17 00:00:00 2001 From: Daniel Van Noord Date: Mon, 30 Sep 2019 08:58:46 -0400 Subject: [PATCH 12/12] Removed unneeded header and cleanup --- linux/hid.c | 1 - windows/hid.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/linux/hid.c b/linux/hid.c index 86fb55166..07ab3e17a 100644 --- a/linux/hid.c +++ b/linux/hid.c @@ -38,7 +38,6 @@ #include /* Linux */ -#include #include #include #include diff --git a/windows/hid.c b/windows/hid.c index 413edcade..a535d3312 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -110,7 +110,7 @@ extern "C" { typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length); typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length); - typedef BOOLEAN(__stdcall *HidD_GetInputReport_)(HANDLE handle, PVOID data, ULONG length); + typedef BOOLEAN (__stdcall *HidD_GetInputReport_)(HANDLE handle, PVOID data, ULONG length); typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len); typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data); typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data);