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;
This commit is contained in:
Daniel Van Noord
2019-11-15 06:55:51 -05:00
committed by Ihor Dutchak
parent 7e91963917
commit 083223e779
6 changed files with 118 additions and 0 deletions

View File

@@ -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().

View File

@@ -1237,6 +1237,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)
{

View File

@@ -790,6 +790,11 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
return res;
}
// 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;
}
void HID_API_EXPORT hid_close(hid_device *dev)
{

View File

@@ -983,6 +983,11 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
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)
{
return get_report(dev, kIOHIDReportTypeInput, data, length);
}
void HID_API_EXPORT hid_close(hid_device *dev)
{
if (!dev)

View File

@@ -14,4 +14,5 @@ EXPORTS
hid_open_path @12
hid_send_feature_report @13
hid_get_feature_report @14
hid_get_input_report @15

View File

@@ -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" */
@@ -109,6 +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_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 +123,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 +214,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);
@@ -821,6 +825,55 @@ 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)
{
#if 0
BOOL res;
res = HidD_GetInputReport(dev->device_handle, data, length);
if (!res) {
register_error(dev, "HidD_GetInputReport");
return -1;
}
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)
{
if (!dev)