Skip to content

Commit 05ffeff

Browse files
MarekPietakapi-no
authored andcommitted
applications: nrf_desktop: Use generic HID feature/output report cbs
Use generic functions to handle HID feature and output reports. This simplifies adding support for new HID reports. Jira: NCSDK-33592 Signed-off-by: Marek Pieta <[email protected]> Signed-off-by: Pawel Dunaj <[email protected]>
1 parent 84dcb91 commit 05ffeff

File tree

2 files changed

+80
-34
lines changed

2 files changed

+80
-34
lines changed

applications/nrf_desktop/src/modules/hids.c

Lines changed: 79 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -192,49 +192,93 @@ static void report_sent_cb(struct bt_conn *conn, void *user_data)
192192
hid_report_sent(conn, report_id, false);
193193
}
194194

195-
static void broadcast_kbd_leds_report(struct bt_hids_rep *rep, struct bt_conn *conn, bool write)
195+
static void output_report_handler_async(struct bt_hids_rep *rep, struct bt_conn *conn, bool write)
196196
{
197-
/* Ignore HID keyboard LEDs report read. */
198197
if (!write) {
198+
/* Ignore reads on output reports. */
199199
return;
200200
}
201201

202-
struct hid_report_event *event = new_hid_report_event(rep->size + 1);
202+
/* Check if report is supported. */
203+
size_t i;
204+
205+
for (i = 0; i < ARRAY_SIZE(output_reports); i++) {
206+
if (rep->id == output_reports[i]) {
207+
break;
208+
}
209+
}
210+
211+
if (i == ARRAY_SIZE(output_reports)) {
212+
LOG_ERR("Unsupported output report ID: 0x%" PRIx8, rep->id);
213+
return;
214+
}
215+
216+
if (rep->size > REPORT_BUFFER_SIZE_OUTPUT_REPORT) {
217+
LOG_ERR("Unsupported output report size %" PRIu8, rep->size);
218+
return;
219+
}
220+
221+
size_t dyndata_len = sizeof(rep->id) + rep->size;
222+
struct hid_report_event *event = new_hid_report_event(dyndata_len);
203223

204224
event->source = conn;
205225
/* Subscriber is not specified for HID output report. */
206226
event->subscriber = NULL;
207-
event->dyndata.data[0] = REPORT_ID_KEYBOARD_LEDS;
208-
memcpy(&event->dyndata.data[1], rep->data, rep->size);
209227

228+
uint8_t *evt_buf = event->dyndata.data;
229+
230+
/* Explicitly add report ID. */
231+
evt_buf[0] = rep->id;
232+
evt_buf++;
233+
234+
memcpy(evt_buf, rep->data, rep->size);
210235
APP_EVENT_SUBMIT(event);
211236
}
212237

213-
static void feature_report_handler(struct bt_hids_rep *rep,
214-
struct bt_conn *conn,
215-
bool write)
238+
static bool is_supported_config_channel_report_id(uint8_t rep_id)
216239
{
217-
if (IS_ENABLED(CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE)) {
218-
if (!write) {
219-
int err = config_channel_transport_get(&cfg_chan_transport,
220-
rep->data,
221-
rep->size);
240+
return ((IS_ENABLED(CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE) &&
241+
(rep_id == REPORT_ID_USER_CONFIG)) ||
242+
(IS_ENABLED(CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT) &&
243+
(rep_id == REPORT_ID_USER_CONFIG_OUT)));
244+
}
222245

223-
if (err) {
224-
LOG_WRN("Failed to process report get");
225-
}
226-
} else {
227-
int err = config_channel_transport_set(&cfg_chan_transport,
228-
rep->data,
229-
rep->size);
246+
static void config_channel_report_handler_async(struct bt_hids_rep *rep, struct bt_conn *conn,
247+
bool write)
248+
{
249+
if (!is_supported_config_channel_report_id(rep->id)) {
250+
LOG_ERR("Not a supported config channel report ID: 0x%" PRIx8, rep->id);
251+
return;
252+
}
230253

231-
if (err) {
232-
LOG_WRN("Failed to process report set");
233-
}
254+
if (!write) {
255+
int err = config_channel_transport_get(&cfg_chan_transport,
256+
rep->data,
257+
rep->size);
258+
if (err) {
259+
LOG_WRN("config_channel_transport_get failed (err: %d)", err);
260+
}
261+
} else {
262+
int err = config_channel_transport_set(&cfg_chan_transport,
263+
rep->data,
264+
rep->size);
265+
if (err) {
266+
LOG_WRN("config_channel_transport_set failed (err: %d)", err);
234267
}
235268
}
236269
}
237270

271+
static void boot_keyboard_output_report_handler(struct bt_hids_rep *rep,
272+
struct bt_conn *conn,
273+
bool write)
274+
{
275+
/* Update the passed report ID. */
276+
struct bt_hids_rep updated_rep = *rep;
277+
278+
updated_rep.id = REPORT_ID_KEYBOARD_LEDS;
279+
return output_report_handler_async(&updated_rep, conn, write);
280+
}
281+
238282
static int module_init(void)
239283
{
240284
/* HID service configuration */
@@ -324,9 +368,9 @@ static int module_init(void)
324368
hids_init_param.inp_rep_group_init.cnt = ir_pos;
325369

326370
if (IS_ENABLED(CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE)) {
327-
feature_report[feat_pos].id = REPORT_ID_USER_CONFIG;
328-
feature_report[feat_pos].size = REPORT_SIZE_USER_CONFIG;
329-
feature_report[feat_pos].handler = feature_report_handler;
371+
feature_report[feat_pos].id = REPORT_ID_USER_CONFIG;
372+
feature_report[feat_pos].size = REPORT_SIZE_USER_CONFIG;
373+
feature_report[feat_pos].handler = config_channel_report_handler_async;
330374

331375
report_index[feature_report[feat_pos].id] = feat_pos;
332376
feat_pos++;
@@ -335,19 +379,20 @@ static int module_init(void)
335379
hids_init_param.feat_rep_group_init.cnt = feat_pos;
336380

337381
if (IS_ENABLED(CONFIG_DESKTOP_HID_REPORT_KEYBOARD_SUPPORT)) {
338-
output_report[or_pos].id = REPORT_ID_KEYBOARD_LEDS;
339-
output_report[or_pos].size = REPORT_SIZE_KEYBOARD_LEDS;
340-
output_report[or_pos].handler = broadcast_kbd_leds_report;
382+
output_report[or_pos].id = REPORT_ID_KEYBOARD_LEDS;
383+
output_report[or_pos].size = REPORT_SIZE_KEYBOARD_LEDS;
384+
output_report[or_pos].handler = output_report_handler_async;
341385

342386
report_index[output_report[or_pos].id] = or_pos;
343387
or_pos++;
344388
}
345389

346390
if (IS_ENABLED(CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT)) {
347-
__ASSERT_NO_MSG(IS_ENABLED(CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE));
348-
output_report[or_pos].id = REPORT_ID_USER_CONFIG_OUT;
349-
output_report[or_pos].size = REPORT_SIZE_USER_CONFIG;
350-
output_report[or_pos].handler = feature_report_handler;
391+
BUILD_ASSERT(!IS_ENABLED(CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT) ||
392+
IS_ENABLED(CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE));
393+
output_report[or_pos].id = REPORT_ID_USER_CONFIG_OUT;
394+
output_report[or_pos].size = REPORT_SIZE_USER_CONFIG;
395+
output_report[or_pos].handler = config_channel_report_handler_async;
351396

352397
report_index[output_report[or_pos].id] = or_pos;
353398
or_pos++;
@@ -365,7 +410,7 @@ static int module_init(void)
365410
if (IS_ENABLED(CONFIG_DESKTOP_HID_BOOT_INTERFACE_KEYBOARD)) {
366411
hids_init_param.is_kb = true;
367412
hids_init_param.boot_kb_notif_handler = boot_keyboard_notif_handler;
368-
hids_init_param.boot_kb_outp_rep_handler = broadcast_kbd_leds_report;
413+
hids_init_param.boot_kb_outp_rep_handler = boot_keyboard_output_report_handler;
369414
}
370415

371416
if (IS_ENABLED(CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE)) {

doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ nRF Desktop
237237

238238
* Use the :c:func:`bt_hids_inp_rep_send_userdata` function to send HID input reports while in report mode.
239239
* Use an extended callback with the notification event to handle subscriptions for HID input reports in report mode (:c:struct:`bt_hids_inp_rep`).
240+
* Use generic callbacks to handle HID feature and output reports.
240241

241242
This approach simplifies the process of adding support for new HID reports.
242243

0 commit comments

Comments
 (0)