From 7d66fa209a7a4689eba6863bc73209f19df4375b Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 7 Sep 2021 17:38:26 -0700
Subject: [PATCH] Fixed double-copy of the report in BlueZ >= 5.56
---
src/hidapi/linux/hid.c | 32 ++++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/src/hidapi/linux/hid.c b/src/hidapi/linux/hid.c
index 19a0d9669d..b9544156d4 100644
--- a/src/hidapi/linux/hid.c
+++ b/src/hidapi/linux/hid.c
@@ -843,20 +843,24 @@ 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)
{
int res;
-
- /* It looks like HIDIOCGFEATURE() on Bluetooth LE devices doesn't return the report number */
- if (dev->needs_ble_hack) {
- data[1] = data[0];
- ++data;
- --length;
- }
- res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data);
- if (res < 0)
- perror("ioctl (GFEATURE)");
- else if (dev->needs_ble_hack)
- ++res;
-
- return res;
+ unsigned char report = data[0];
+
+ res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data);
+ if (res < 0)
+ perror("ioctl (GFEATURE)");
+ else if (dev->needs_ble_hack) {
+ /* Versions of BlueZ before 5.56 don't include the report in the data, and versions of BlueZ >= 5.56 include 2 copies of the report.
+ * We'll fix it so that there is a single copy of the report in both cases
+ */
+ if (data[0] == report && data[1] == report) {
+ memmove(&data[0], &data[1], res);
+ } else if (data[0] != report) {
+ memmove(&data[1], &data[0], res);
+ data[0] = report;
+ ++res;
+ }
+ }
+ return res;
}