Skip to content

Commit 73e77b3

Browse files
MarekPietanordicjm
authored andcommitted
applications: nrf_desktop: Support hid_subscriber_event in hid_forward
Change adds support for hid_subscriber_event to HID forward module. Jira: NCSDK-25200 Signed-off-by: Marek Pieta <[email protected]>
1 parent 5a37179 commit 73e77b3

File tree

1 file changed

+130
-119
lines changed

1 file changed

+130
-119
lines changed

applications/nrf_desktop/src/modules/hid_forward.c

Lines changed: 130 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ struct subscriber {
6464
struct enqueued_reports enqueued_reports;
6565
struct report_data out_reports[ARRAY_SIZE(output_reports)];
6666
uint32_t saved_out_reports_bm;
67-
bool busy;
67+
uint8_t report_max;
68+
uint8_t report_cnt;
6869
};
6970

7071
struct hids_peripheral {
@@ -88,7 +89,6 @@ static bool suspended;
8889

8990
static void hogp_out_rep_write_cb(struct bt_hogp *hogp, struct bt_hogp_rep_info *rep, uint8_t err);
9091
static int send_hid_out_report(struct bt_hogp *hogp, const uint8_t *data, size_t size);
91-
static void send_empty_hid_out_reports(struct hids_peripheral *per, struct subscriber *sub);
9292

9393
#if CONFIG_DESKTOP_HID_DONGLE_BOND_COUNT > 1
9494
static void verify_data(const struct bt_bond_info *info, void *user_data)
@@ -353,12 +353,12 @@ static void forward_hid_report(struct hids_peripheral *per, uint8_t report_id,
353353
report->dyndata.data[0] = report_id;
354354
memcpy(&report->dyndata.data[1], data, size);
355355

356-
if (!sub->busy) {
356+
if (sub->report_cnt < sub->report_max) {
357357
__ASSERT_NO_MSG(!is_report_enqueued(&sub->enqueued_reports, irep_idx));
358358

359359
APP_EVENT_SUBMIT(report);
360360
sub->enqueued_reports.last_idx = irep_idx;
361-
sub->busy = true;
361+
sub->report_cnt++;
362362
} else {
363363
enqueue_hid_report(&sub->enqueued_reports, irep_idx, report);
364364
}
@@ -984,27 +984,7 @@ static void disable_subscription(struct subscriber *sub, uint8_t report_id)
984984
}
985985

986986
WRITE_BIT(sub->enabled_reports_bm, report_id, 0);
987-
bool sub_disconnected = (sub->enabled_reports_bm == 0);
988-
989-
/* For all peripherals connected to this subscriber. */
990-
for (size_t per_id = 0; per_id < ARRAY_SIZE(peripherals); per_id++) {
991-
struct hids_peripheral *per = &peripherals[per_id];
992-
993-
if ((sub != get_subscriber(per)) ||
994-
(!is_peripheral_connected(per))) {
995-
continue;
996-
}
997-
998-
if (sub_disconnected) {
999-
send_empty_hid_out_reports(per, sub);
1000-
}
1001-
}
1002-
1003987
drop_enqueued_reports(&sub->enqueued_reports, irep_idx);
1004-
1005-
if (sub_disconnected) {
1006-
sub->saved_out_reports_bm = 0;
1007-
}
1008988
}
1009989

1010990
static void hogp_ready(struct bt_hogp *hids_c)
@@ -1119,21 +1099,19 @@ static void init(void)
11191099

11201100
static void send_enqueued_report(struct subscriber *sub)
11211101
{
1122-
if (sub->busy) {
1123-
return;
1124-
}
1125-
1126-
struct enqueued_report *item;
1102+
__ASSERT_NO_MSG(sub->report_cnt <= sub->report_max);
11271103

1128-
/* First try to send report left at subscriber. */
1129-
item = get_next_enqueued_report(&sub->enqueued_reports);
1104+
while (sub->report_cnt != sub->report_max) {
1105+
struct enqueued_report *item = get_next_enqueued_report(&sub->enqueued_reports);
11301106

1131-
if (item) {
1132-
APP_EVENT_SUBMIT(item->report);
1107+
if (item) {
1108+
APP_EVENT_SUBMIT(item->report);
11331109

1134-
k_free(item);
1135-
1136-
sub->busy = true;
1110+
k_free(item);
1111+
sub->report_cnt++;
1112+
} else {
1113+
break;
1114+
}
11371115
}
11381116
}
11391117

@@ -1196,27 +1174,6 @@ static void hogp_out_rep_write_cb(struct bt_hogp *hogp, struct bt_hogp_rep_info
11961174
WRITE_BIT(per->enqueued_out_reports_bm, orep_idx, 0);
11971175
}
11981176

1199-
static void send_empty_hid_out_reports(struct hids_peripheral *per, struct subscriber *sub)
1200-
{
1201-
struct bt_hogp *per_hogp = &per->hogp;
1202-
1203-
for (size_t orep_idx = 0; orep_idx < ARRAY_SIZE(sub->out_reports); orep_idx++) {
1204-
if (sub->saved_out_reports_bm & BIT(orep_idx)) {
1205-
uint8_t report_id = sub->out_reports[orep_idx].report_id;
1206-
size_t size = get_output_report_size(report_id);
1207-
uint8_t empty_data[size];
1208-
1209-
memset(empty_data, 0, sizeof(empty_data));
1210-
empty_data[0] = report_id;
1211-
int err = send_hid_out_report(per_hogp, empty_data, size);
1212-
1213-
if (err) {
1214-
LOG_ERR("Failed to forward output report (err: %d)", err);
1215-
}
1216-
}
1217-
}
1218-
}
1219-
12201177
static void save_hid_out_report(struct subscriber *sub, const uint8_t *data, size_t size)
12211178
{
12221179
uint8_t report_id = data[0];
@@ -1258,34 +1215,126 @@ static void forward_hid_out_report(const struct hid_report_event *event,
12581215
}
12591216
}
12601217

1261-
static bool handle_hid_report_event(const struct hid_report_event *event)
1218+
static struct subscriber *find_subscriber(const void *sub_id)
12621219
{
1263-
/* Ignore HID input events. */
1264-
if (event->subscriber) {
1265-
return false;
1220+
struct subscriber *sub = NULL;
1221+
1222+
for (size_t i = 0; i < ARRAY_SIZE(subscribers); i++) {
1223+
if (subscribers[i].id == sub_id) {
1224+
sub = &subscribers[i];
1225+
break;
1226+
}
12661227
}
12671228

1268-
size_t sub_idx;
1229+
return sub;
1230+
}
12691231

1270-
for (sub_idx = 0; sub_idx < ARRAY_SIZE(subscribers); sub_idx++) {
1271-
if (subscribers[sub_idx].id == event->source) {
1272-
break;
1232+
static void send_empty_hid_out_reports(struct hids_peripheral *per, struct subscriber *sub)
1233+
{
1234+
struct bt_hogp *per_hogp = &per->hogp;
1235+
1236+
for (size_t orep_idx = 0; orep_idx < ARRAY_SIZE(sub->out_reports); orep_idx++) {
1237+
if (sub->saved_out_reports_bm & BIT(orep_idx)) {
1238+
uint8_t report_id = sub->out_reports[orep_idx].report_id;
1239+
size_t size = get_output_report_size(report_id);
1240+
uint8_t empty_data[size];
1241+
1242+
memset(empty_data, 0, sizeof(empty_data));
1243+
empty_data[0] = report_id;
1244+
int err = send_hid_out_report(per_hogp, empty_data, size);
1245+
1246+
if (err) {
1247+
LOG_ERR("Failed to forward output report (err: %d)", err);
1248+
}
12731249
}
12741250
}
1251+
}
1252+
1253+
static void clear_hid_out_reports(struct subscriber *sub)
1254+
{
1255+
/* Update HID peripherals. */
1256+
for (size_t per_id = 0; per_id < ARRAY_SIZE(peripherals); per_id++) {
1257+
struct hids_peripheral *per = &peripherals[per_id];
1258+
1259+
if ((sub == get_subscriber(per)) && is_peripheral_connected(per)) {
1260+
send_empty_hid_out_reports(per, sub);
1261+
}
1262+
1263+
}
1264+
1265+
sub->saved_out_reports_bm = 0;
1266+
}
12751267

1276-
if (sub_idx == ARRAY_SIZE(subscribers)) {
1277-
LOG_WRN("No subscriber with ID: %p", event->source);
1268+
static bool handle_hid_report_subscriber_event(const struct hid_report_subscriber_event *event)
1269+
{
1270+
if (event->connected) {
1271+
/* The HID forward module forwards data received from HID peripherals connected over
1272+
* BLE and does not generate HID data pipeline.
1273+
*/
1274+
ARG_UNUSED(event->params.pipeline_size);
1275+
ARG_UNUSED(event->params.priority);
1276+
1277+
/* Allocate new subscriber. */
1278+
struct subscriber *sub = find_subscriber(NULL);
1279+
1280+
__ASSERT_NO_MSG(sub);
1281+
sub->id = event->subscriber;
1282+
sub->report_max = event->params.report_max;
1283+
} else {
1284+
struct subscriber *sub = find_subscriber(event->subscriber);
1285+
1286+
__ASSERT_NO_MSG(sub);
1287+
1288+
__ASSERT_NO_MSG(sub->report_cnt == 0);
1289+
__ASSERT_NO_MSG(sub->enabled_reports_bm == 0);
1290+
__ASSERT_NO_MSG(get_next_enqueued_report(&sub->enqueued_reports) == NULL);
1291+
1292+
sub->report_max = 0;
1293+
clear_hid_out_reports(sub);
1294+
sub->id = NULL;
1295+
}
1296+
1297+
return false;
1298+
}
1299+
1300+
static bool handle_hid_report_subscription_event(const struct hid_report_subscription_event *event)
1301+
{
1302+
struct subscriber *sub = find_subscriber(event->subscriber);
1303+
1304+
__ASSERT_NO_MSG(sub);
1305+
__ASSERT_NO_MSG(event->report_id < __CHAR_BIT__ * sizeof(sub->enabled_reports_bm));
1306+
enum bt_hids_pm prev_pm = get_sub_protocol_mode(sub);
1307+
1308+
if (event->enabled) {
1309+
enable_subscription(sub, event->report_id);
1310+
send_enqueued_report(sub);
1311+
} else {
1312+
disable_subscription(sub, event->report_id);
1313+
}
1314+
1315+
if (prev_pm != get_sub_protocol_mode(sub)) {
1316+
update_sub_protocol_mode(sub, get_sub_protocol_mode(sub));
1317+
}
1318+
1319+
return false;
1320+
}
1321+
1322+
static bool handle_hid_report_event(const struct hid_report_event *event)
1323+
{
1324+
/* Ignore HID input events. */
1325+
if (event->subscriber) {
12781326
return false;
12791327
}
12801328

1281-
save_hid_out_report(&subscribers[sub_idx],
1282-
event->dyndata.data,
1283-
event->dyndata.size);
1329+
struct subscriber *sub = find_subscriber(event->source);
1330+
1331+
__ASSERT_NO_MSG(sub);
1332+
save_hid_out_report(sub, event->dyndata.data, event->dyndata.size);
12841333

12851334
for (size_t i = 0; i < ARRAY_SIZE(peripherals); i++) {
12861335
struct hids_peripheral *per = &peripherals[i];
12871336

1288-
if ((per->sub_id == sub_idx) && is_peripheral_connected(per)) {
1337+
if ((get_subscriber(per) == sub) && is_peripheral_connected(per)) {
12891338
forward_hid_out_report(event, per);
12901339
}
12911340
}
@@ -1296,19 +1345,11 @@ static bool handle_hid_report_event(const struct hid_report_event *event)
12961345
static bool app_event_handler(const struct app_event_header *aeh)
12971346
{
12981347
if (is_hid_report_sent_event(aeh)) {
1299-
const struct hid_report_sent_event *event =
1300-
cast_hid_report_sent_event(aeh);
1301-
struct subscriber *sub = NULL;
1348+
const struct hid_report_sent_event *event = cast_hid_report_sent_event(aeh);
1349+
struct subscriber *sub = find_subscriber(event->subscriber);
13021350

1303-
for (size_t i = 0; i < ARRAY_SIZE(subscribers); i++) {
1304-
if (subscribers[i].id == event->subscriber) {
1305-
sub = &subscribers[i];
1306-
break;
1307-
}
1308-
}
13091351
__ASSERT_NO_MSG(sub);
1310-
1311-
sub->busy = false;
1352+
sub->report_cnt--;
13121353
send_enqueued_report(sub);
13131354

13141355
return false;
@@ -1342,44 +1383,13 @@ static bool app_event_handler(const struct app_event_header *aeh)
13421383
return false;
13431384
}
13441385

1345-
if (is_hid_report_subscription_event(aeh)) {
1346-
const struct hid_report_subscription_event *event =
1347-
cast_hid_report_subscription_event(aeh);
1348-
1349-
struct subscriber *sub = NULL;
1350-
1351-
for (size_t i = 0; i < ARRAY_SIZE(subscribers); i++) {
1352-
if ((subscribers[i].id == event->subscriber) ||
1353-
(subscribers[i].id == NULL)) {
1354-
sub = &subscribers[i];
1355-
}
1356-
1357-
if (subscribers[i].id == event->subscriber) {
1358-
break;
1359-
}
1360-
}
1361-
__ASSERT_NO_MSG(sub);
1362-
1363-
if (!sub->id) {
1364-
sub->id = event->subscriber;
1365-
}
1366-
1367-
__ASSERT_NO_MSG(event->report_id < __CHAR_BIT__ * sizeof(sub->enabled_reports_bm));
1368-
1369-
enum bt_hids_pm prev_pm = get_sub_protocol_mode(sub);
1370-
1371-
if (event->enabled) {
1372-
enable_subscription(sub, event->report_id);
1373-
send_enqueued_report(sub);
1374-
} else {
1375-
disable_subscription(sub, event->report_id);
1376-
}
1377-
1378-
if (prev_pm != get_sub_protocol_mode(sub)) {
1379-
update_sub_protocol_mode(sub, get_sub_protocol_mode(sub));
1380-
}
1386+
if (is_hid_report_subscriber_event(aeh)) {
1387+
return handle_hid_report_subscriber_event(cast_hid_report_subscriber_event(aeh));
1388+
}
13811389

1382-
return false;
1390+
if (is_hid_report_subscription_event(aeh)) {
1391+
return handle_hid_report_subscription_event(
1392+
cast_hid_report_subscription_event(aeh));
13831393
}
13841394

13851395
if (is_hid_report_event(aeh)) {
@@ -1446,6 +1456,7 @@ APP_EVENT_SUBSCRIBE_EARLY(MODULE, ble_discovery_complete_event);
14461456
APP_EVENT_SUBSCRIBE(MODULE, ble_peer_event);
14471457
APP_EVENT_SUBSCRIBE(MODULE, ble_peer_operation_event);
14481458
APP_EVENT_SUBSCRIBE(MODULE, hid_report_event);
1459+
APP_EVENT_SUBSCRIBE(MODULE, hid_report_subscriber_event);
14491460
APP_EVENT_SUBSCRIBE(MODULE, hid_report_subscription_event);
14501461
APP_EVENT_SUBSCRIBE(MODULE, hid_report_sent_event);
14511462
APP_EVENT_SUBSCRIBE(MODULE, power_down_event);

0 commit comments

Comments
 (0)