From 35a2c50437cca4d26ac6537ce3a964bb509c9b62 Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Fri, 20 Nov 2020 12:42:46 +1100 Subject: [PATCH] hog: Fix stripping off read report bytes If the HID subsystem requests a HID report to be read from the device, we currently incorrectly strip off the first byte of the response, if the device has report IDs set in the HID report descriptor. This is incorrect; unlike USB HID, the report ID is *not* included in the HOG profile's HID reports, and instead exists out of band in a descriptor on the report's bluetooth characteristic in the device. In this patch, we remove the erroneous stripping of the first byte of the report, and (if report IDs are enabled) prepend the report ID to the front of the result. This makes the HID report returned indentical in format to that of a USB HID report, so that the upper HID drivers can consume HOG device reports in the same way as USB. --- profiles/input/hog-lib.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c index 78018aad3..ee811d301 100644 --- a/profiles/input/hog-lib.c +++ b/profiles/input/hog-lib.c @@ -779,7 +779,8 @@ fail: static void get_report_cb(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data) { - struct bt_hog *hog = user_data; + struct report *report = user_data; + struct bt_hog *hog = report->hog; struct uhid_event rsp; int err; @@ -808,14 +809,16 @@ static void get_report_cb(guint8 status, const guint8 *pdu, guint16 len, --len; ++pdu; + if (hog->has_report_id && len > 0) { - --len; - ++pdu; + rsp.u.get_report_reply.size = len + 1; + rsp.u.get_report_reply.data[0] = report->id; + memcpy(&rsp.u.get_report_reply.data[1], pdu, len); + } else { + rsp.u.get_report_reply.size = len; + memcpy(rsp.u.get_report_reply.data, pdu, len); } - rsp.u.get_report_reply.size = len; - memcpy(rsp.u.get_report_reply.data, pdu, len); - exit: rsp.u.get_report_reply.err = status; err = bt_uhid_send(hog->uhid, &rsp); @@ -846,7 +849,7 @@ static void get_report(struct uhid_event *ev, void *user_data) hog->getrep_att = gatt_read_char(hog->attrib, report->value_handle, - get_report_cb, hog); + get_report_cb, report); if (!hog->getrep_att) { err = ENOMEM; goto fail; -- 2.47.3