Skip to content

Commit 4336c31

Browse files
Merge pull request #8 from RobertDaleSmith/sgowda/hid-update
updating descriptor
2 parents 6172ba8 + b0bb483 commit 4336c31

2 files changed

Lines changed: 93 additions & 20 deletions

File tree

ncs/app/src/ble_hid.c

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,40 @@ LOG_MODULE_REGISTER(ble_hid, LOG_LEVEL_INF);
4141
static ble_hid_data_received_cb_t data_received_callback = NULL;
4242
static ble_hid_ready_cb_t ready_callback = NULL;
4343

44+
/**
45+
* Consumer Control usage codes for backwards compatibility.
46+
* Maps old 1-byte bitmap format to new 16-bit usage selector format.
47+
* Old firmware used 8 individual bit flags, new descriptor uses usage codes.
48+
*/
49+
static const uint16_t consumer_bitmap_to_usage[] = {
50+
0x00CD, /* bit 0: Play/Pause */
51+
0x0183, /* bit 1: AL Consumer Control Configuration */
52+
0x00B5, /* bit 2: Scan Next Track */
53+
0x00B6, /* bit 3: Scan Previous Track */
54+
0x00EA, /* bit 4: Volume Decrement */
55+
0x00E9, /* bit 5: Volume Increment */
56+
0x0225, /* bit 6: AC Forward */
57+
0x0224, /* bit 7: AC Back */
58+
};
59+
60+
/**
61+
* Translate old consumer control bitmap to new 16-bit usage format.
62+
* Returns the usage code for the first set bit, or 0 if no bits set.
63+
*/
64+
static uint16_t translate_consumer_bitmap(uint8_t bitmap)
65+
{
66+
if (bitmap == 0) {
67+
return 0;
68+
}
69+
/* Find first set bit and return corresponding usage */
70+
for (int i = 0; i < 8; i++) {
71+
if (bitmap & (1 << i)) {
72+
return consumer_bitmap_to_usage[i];
73+
}
74+
}
75+
return 0;
76+
}
77+
4478
/**
4579
* Switch between boot protocol and report protocol mode.
4680
*/
@@ -172,14 +206,29 @@ static uint8_t hogp_notify_cb(struct bt_hogp *hogp,
172206

173207
// Parse and forward each report ID independently
174208
if (size >= 1) {
175-
/* Send directly to USB for zero latency */
176-
uint8_t report_with_id[size + 1];
177-
report_with_id[0] = report_id;
178-
for (uint8_t i = 0; i < size; i++) {
179-
report_with_id[i + 1] = data[i];
209+
int ret;
210+
211+
/* Handle Report ID 3 (Consumer Control) backwards compatibility */
212+
if (report_id == 3 && size == 1) {
213+
/* Old firmware sends 1-byte bitmap, translate to 16-bit usage */
214+
uint16_t usage = translate_consumer_bitmap(data[0]);
215+
uint8_t consumer_report[3] = {
216+
0x03, /* Report ID 3 */
217+
usage & 0xFF, /* Usage low byte */
218+
(usage >> 8) & 0xFF /* Usage high byte */
219+
};
220+
LOG_DBG("Consumer control: bitmap 0x%02x -> usage 0x%04x", data[0], usage);
221+
ret = hid_device_submit_report(hid_dev, sizeof(consumer_report), consumer_report);
222+
} else {
223+
/* Send directly to USB for zero latency */
224+
uint8_t report_with_id[size + 1];
225+
report_with_id[0] = report_id;
226+
for (uint8_t i = 0; i < size; i++) {
227+
report_with_id[i + 1] = data[i];
228+
}
229+
ret = hid_device_submit_report(hid_dev, size + 1, report_with_id);
180230
}
181231

182-
int ret = hid_device_submit_report(hid_dev, size + 1, report_with_id);
183232
if (ret) {
184233
LOG_ERR("HID write error, %d", ret);
185234
} else {

ncs/app/src/usb_hid.c

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,18 @@ static bool usb_enumerated = false;
5959
* This descriptor matches the MouthPad BLE device exactly to eliminate scaling
6060
*/
6161
static const uint8_t hid_report_desc[] = {
62-
0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x85, 0x01, 0x09, 0x01, 0xA1, 0x00,
63-
0x95, 0x05, 0x75, 0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x05, 0x15, 0x00,
64-
0x25, 0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x03, 0x81, 0x01, 0x75, 0x08,
65-
0x95, 0x01, 0x05, 0x01, 0x09, 0x38, 0x15, 0x81, 0x25, 0x7F, 0x81, 0x06,
66-
0x05, 0x0C, 0x0A, 0x38, 0x02, 0x95, 0x01, 0x81, 0x06, 0xC0, 0x85, 0x02,
67-
0x09, 0x01, 0xA1, 0x00, 0x75, 0x0C, 0x95, 0x02, 0x05, 0x01, 0x09, 0x30,
68-
0x09, 0x31, 0x16, 0x01, 0xF8, 0x26, 0xFF, 0x07, 0x81, 0x06, 0xC0, 0xC0,
69-
0x05, 0x0C, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x03, 0x15, 0x00, 0x25, 0x01,
70-
0x75, 0x01, 0x95, 0x01, 0x09, 0xCD, 0x81, 0x06, 0x0A, 0x83, 0x01, 0x81,
71-
0x06, 0x09, 0xB5, 0x81, 0x06, 0x09, 0xB6, 0x81, 0x06, 0x09, 0xEA, 0x81,
72-
0x06, 0x09, 0xE9, 0x81, 0x06, 0x0A, 0x25, 0x02, 0x81, 0x06, 0x0A, 0x24,
73-
0x02, 0x81, 0x06, 0xC0
62+
0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x85, 0x01, 0x09, 0x01, 0xA1, 0x00, 0x95,
63+
0x05, 0x75, 0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x05, 0x15, 0x00, 0x25, 0x01,
64+
0x81, 0x02, 0x95, 0x01, 0x75, 0x03, 0x81, 0x01, 0x75, 0x08, 0x95, 0x01, 0x05,
65+
0x01, 0x09, 0x38, 0x15, 0x81, 0x25, 0x7F, 0x81, 0x06, 0x05, 0x0C, 0x0A, 0x38,
66+
0x02, 0x95, 0x01, 0x81, 0x06, 0xC0, 0x85, 0x02, 0x09, 0x01, 0xA1, 0x00, 0x75,
67+
0x0C, 0x95, 0x02, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x16, 0x01, 0xF8, 0x26,
68+
0xFF, 0x07, 0x81, 0x06, 0xC0, 0x85, 0x03, 0x05, 0x0C, 0x19, 0x00, 0x2A, 0x3C,
69+
0x02, 0x15, 0x00, 0x26, 0x3C, 0x02, 0x75, 0x10, 0x95, 0x01, 0x81, 0x00, 0xC0,
70+
0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x85, 0x04, 0x05, 0x07, 0x19, 0xE0, 0x29,
71+
0xE7, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01,
72+
0x75, 0x08, 0x81, 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05,
73+
0x07, 0x19, 0x00, 0x29, 0x65, 0x81, 0x00, 0xC0
7474
};
7575

7676
/* ============================================================================
@@ -453,10 +453,24 @@ int usb_hid_send_release_all(void)
453453
0x00 /* Y high byte = 0 */
454454
};
455455

456-
/* Report ID 3: Release all consumer controls */
456+
/* Report ID 3: Release all consumer controls (16-bit usage selector) */
457457
uint8_t report3[] = {
458458
0x03, /* Report ID 3 */
459-
0x00 /* No consumer controls pressed */
459+
0x00, /* Consumer control usage low byte */
460+
0x00 /* Consumer control usage high byte */
461+
};
462+
463+
/* Report ID 4: Release all keyboard keys */
464+
uint8_t report4[] = {
465+
0x04, /* Report ID 4 */
466+
0x00, /* Modifier keys */
467+
0x00, /* Reserved */
468+
0x00, /* Key 1 */
469+
0x00, /* Key 2 */
470+
0x00, /* Key 3 */
471+
0x00, /* Key 4 */
472+
0x00, /* Key 5 */
473+
0x00 /* Key 6 */
460474
};
461475

462476
/* Send clear reports 3 times to ensure USB host processes them */
@@ -491,6 +505,16 @@ int usb_hid_send_release_all(void)
491505
} else {
492506
LOG_INF("Release report 3 sent round %d (consumer controls cleared)", round + 1);
493507
}
508+
k_msleep(10); /* 10ms delay between reports */
509+
510+
/* Send Report 4 - Release keyboard keys */
511+
ret = usb_hid_send_report(report4, sizeof(report4));
512+
if (ret != 0) {
513+
LOG_ERR("Failed to send release report 4 round %d (err %d)", round + 1, ret);
514+
failed_count++;
515+
} else {
516+
LOG_INF("Release report 4 sent round %d (keyboard cleared)", round + 1);
517+
}
494518

495519
if (round < 2) {
496520
k_msleep(20); /* Longer delay between rounds */

0 commit comments

Comments
 (0)