Skip to content

Commit 083223e

Browse files
DanielVanNoordYouw
authored andcommitted
Added support for Get Input Report (#59)
- Get Input Report supported on linux/libusb, mac and windows; - linux/hidraw doesn't support it on kernel level;
1 parent 7e91963 commit 083223e

File tree

6 files changed

+118
-0
lines changed

6 files changed

+118
-0
lines changed

hidapi/hidapi.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,31 @@ extern "C" {
334334
*/
335335
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length);
336336

337+
/** @brief Get a input report from a HID device.
338+
339+
Set the first byte of @p data[] to the Report ID of the
340+
report to be read. Make sure to allow space for this
341+
extra byte in @p data[]. Upon return, the first byte will
342+
still contain the Report ID, and the report data will
343+
start in data[1].
344+
345+
@ingroup API
346+
@param device A device handle returned from hid_open().
347+
@param data A buffer to put the read data into, including
348+
the Report ID. Set the first byte of @p data[] to the
349+
Report ID of the report to be read, or set it to zero
350+
if your device does not use numbered reports.
351+
@param length The number of bytes to read, including an
352+
extra byte for the report ID. The buffer can be longer
353+
than the actual report.
354+
355+
@returns
356+
This function returns the number of bytes read plus
357+
one for the report ID (which is still in the first
358+
byte), or -1 on error.
359+
*/
360+
int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length);
361+
337362
/** @brief Close a HID device.
338363
339364
This function sets the return value of hid_error().

libusb/hid.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,35 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
12371237
return res;
12381238
}
12391239

1240+
int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
1241+
{
1242+
int res = -1;
1243+
int skipped_report_id = 0;
1244+
int report_number = data[0];
1245+
1246+
if (report_number == 0x0) {
1247+
/* Offset the return buffer by 1, so that the report ID
1248+
will remain in byte 0. */
1249+
data++;
1250+
length--;
1251+
skipped_report_id = 1;
1252+
}
1253+
res = libusb_control_transfer(dev->device_handle,
1254+
LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN,
1255+
0x01/*HID get_report*/,
1256+
(1/*HID Input*/ << 8) | report_number,
1257+
dev->interface,
1258+
(unsigned char *)data, length,
1259+
1000/*timeout millis*/);
1260+
1261+
if (res < 0)
1262+
return -1;
1263+
1264+
if (skipped_report_id)
1265+
res++;
1266+
1267+
return res;
1268+
}
12401269

12411270
void HID_API_EXPORT hid_close(hid_device *dev)
12421271
{

linux/hid.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,11 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
790790
return res;
791791
}
792792

793+
// Not supported by Linux HidRaw yet
794+
int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
795+
{
796+
return -1;
797+
}
793798

794799
void HID_API_EXPORT hid_close(hid_device *dev)
795800
{

mac/hid.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,11 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
983983
return get_report(dev, kIOHIDReportTypeFeature, data, length);
984984
}
985985

986+
int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
987+
{
988+
return get_report(dev, kIOHIDReportTypeInput, data, length);
989+
}
990+
986991
void HID_API_EXPORT hid_close(hid_device *dev)
987992
{
988993
if (!dev)

windows/ddk_build/hidapi.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ EXPORTS
1414
hid_open_path @12
1515
hid_send_feature_report @13
1616
hid_get_feature_report @14
17+
hid_get_input_report @15
1718

windows/hid.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ extern "C" {
5555
#define HID_OUT_CTL_CODE(id) \
5656
CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
5757
#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100)
58+
#define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104)
5859

5960
#ifdef __cplusplus
6061
} /* extern "C" */
@@ -109,6 +110,7 @@ extern "C" {
109110
typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
110111
typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length);
111112
typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length);
113+
typedef BOOLEAN (__stdcall *HidD_GetInputReport_)(HANDLE handle, PVOID data, ULONG length);
112114
typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len);
113115
typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data);
114116
typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data);
@@ -121,6 +123,7 @@ extern "C" {
121123
static HidD_GetProductString_ HidD_GetProductString;
122124
static HidD_SetFeature_ HidD_SetFeature;
123125
static HidD_GetFeature_ HidD_GetFeature;
126+
static HidD_GetInputReport_ HidD_GetInputReport;
124127
static HidD_GetIndexedString_ HidD_GetIndexedString;
125128
static HidD_GetPreparsedData_ HidD_GetPreparsedData;
126129
static HidD_FreePreparsedData_ HidD_FreePreparsedData;
@@ -211,6 +214,7 @@ static int lookup_functions()
211214
RESOLVE(HidD_GetProductString);
212215
RESOLVE(HidD_SetFeature);
213216
RESOLVE(HidD_GetFeature);
217+
RESOLVE(HidD_GetInputReport);
214218
RESOLVE(HidD_GetIndexedString);
215219
RESOLVE(HidD_GetPreparsedData);
216220
RESOLVE(HidD_FreePreparsedData);
@@ -821,6 +825,55 @@ int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned
821825
#endif
822826
}
823827

828+
829+
int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
830+
{
831+
#if 0
832+
BOOL res;
833+
res = HidD_GetInputReport(dev->device_handle, data, length);
834+
if (!res) {
835+
register_error(dev, "HidD_GetInputReport");
836+
return -1;
837+
}
838+
return length;
839+
#else
840+
DWORD bytes_returned;
841+
842+
OVERLAPPED ol;
843+
memset(&ol, 0, sizeof(ol));
844+
845+
BOOL res = DeviceIoControl(dev->device_handle,
846+
IOCTL_HID_GET_INPUT_REPORT,
847+
data, length,
848+
data, length,
849+
&bytes_returned, &ol);
850+
851+
if (!res) {
852+
if (GetLastError() != ERROR_IO_PENDING) {
853+
/* DeviceIoControl() failed. Return error. */
854+
register_error(dev, "Send Input Report DeviceIoControl");
855+
return -1;
856+
}
857+
}
858+
859+
/* Wait here until the write is done. This makes
860+
hid_get_feature_report() synchronous. */
861+
res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/);
862+
if (!res) {
863+
/* The operation failed. */
864+
register_error(dev, "Send Input Report GetOverLappedResult");
865+
return -1;
866+
}
867+
868+
/* bytes_returned does not include the first byte which contains the
869+
report ID. The data buffer actually contains one more byte than
870+
bytes_returned. */
871+
bytes_returned++;
872+
873+
return bytes_returned;
874+
#endif
875+
}
876+
824877
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev)
825878
{
826879
if (!dev)

0 commit comments

Comments
 (0)