Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions app/src/split/bluetooth/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,17 @@ config BT_GAP_AUTO_UPDATE_CONN_PARAMS

endif # !ZMK_SPLIT_ROLE_CENTRAL

if ZMK_INPUT_SPLIT

config ZMK_INPUT_SPLIT_MSG_QUEUE_SIZE
int "Max number of input split messages to queue for sending over BLE"
default 32
help
Sets the maximum number of input split events that can be queued for BLE notifications.
Increasing this reduces drops during high-rate input bursts at the cost of additional RAM.

endif # ZMK_INPUT_SPLIT

endmenu

endif # ZMK_SPLIT_BLE
40 changes: 39 additions & 1 deletion app/src/split/bluetooth/service.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,27 @@ static int zmk_split_bt_sensor_triggered(uint8_t sensor_index,

#if IS_ENABLED(CONFIG_ZMK_INPUT_SPLIT)

struct input_event_notify_item {
uint16_t attr_index;
struct zmk_split_input_event_payload payload;
};

K_MSGQ_DEFINE(input_event_msgq, sizeof(struct input_event_notify_item),
CONFIG_ZMK_INPUT_SPLIT_MSG_QUEUE_SIZE, 4);

static void send_input_event_callback(struct k_work *work) {
struct input_event_notify_item item;
while (k_msgq_get(&input_event_msgq, &item, K_NO_WAIT) == 0) {
int err = bt_gatt_notify(NULL, &split_svc.attrs[item.attr_index], &item.payload,
sizeof(item.payload));
if (err) {
LOG_ERR("Error notifying input event %d", err);
}
}
}

static K_WORK_DEFINE(service_input_notify_work, send_input_event_callback);

static int zmk_split_bt_report_input(uint8_t reg, uint8_t type, uint16_t code, int32_t value,
bool sync) {

Expand All @@ -326,7 +347,24 @@ static int zmk_split_bt_report_input(uint8_t reg, uint8_t type, uint16_t code, i
.sync = sync ? 1 : 0,
};

return bt_gatt_notify(NULL, &split_svc.attrs[i], &payload, sizeof(payload));
struct input_event_notify_item item = {.attr_index = (uint16_t)i, .payload = payload};
int err = k_msgq_put(&input_event_msgq, &item, K_NO_WAIT);

if (err == 0) {
k_work_submit_to_queue(&service_work_q, &service_input_notify_work);
return 0;
} else {
LOG_WRN("Input event queue full, dropping one and retry");

struct input_event_notify_item discarded;
k_msgq_get(&input_event_msgq, &discarded, K_NO_WAIT);
err = k_msgq_put(&input_event_msgq, &item, K_NO_WAIT);

if (err != 0) {
LOG_WRN("Failed to queue input event (%d)", err);
return err;
}
}
}
}
return -ENODEV;
Expand Down