From 4aa78a6f8d2742e1407f78c50a0cf93e194447a4 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Thu, 3 Dec 2020 00:12:21 -0500 Subject: [PATCH] fix(split): Use queue/work for peripheral events. * Avoid corruption by using work to process peripheral key position events on the main work thread, like local kscan events are. * Fixes #221 --- app/Kconfig | 10 +++++++- app/src/split/bluetooth/central.c | 41 +++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/app/Kconfig b/app/Kconfig index 0aa291d6..65abf7a5 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -94,11 +94,19 @@ config ZMK_SPLIT_BLE if ZMK_SPLIT_BLE -config ZMK_SPLIT_BLE_ROLE_CENTRAL +menuconfig ZMK_SPLIT_BLE_ROLE_CENTRAL bool "Central" select BT_CENTRAL select BT_GATT_CLIENT +if ZMK_SPLIT_BLE_ROLE_CENTRAL + +config ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE + int "Max number of key position state events to queue when received from peripherals" + default 5 + +endif + if !ZMK_SPLIT_BLE_ROLE_CENTRAL config ZMK_USB diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index 5ad83ad2..9cce7870 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -33,9 +33,32 @@ static struct bt_uuid_128 uuid = BT_UUID_INIT_128(ZMK_SPLIT_BT_SERVICE_UUID); static struct bt_gatt_discover_params discover_params; static struct bt_gatt_subscribe_params subscribe_params; -static uint8_t split_central_notify_func(struct bt_conn *conn, - struct bt_gatt_subscribe_params *params, const void *data, - uint16_t length) { +struct zmk_split_peripheral_event { + uint32_t position; + uint32_t state; + int32_t timestamp; +}; + +K_MSGQ_DEFINE(peripheral_event_msgq, sizeof(struct zmk_split_peripheral_event), + CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE, 4); + +void peripheral_event_work_callback(struct k_work *work) { + struct zmk_split_peripheral_event ev; + while (k_msgq_get(&peripheral_event_msgq, &ev, K_NO_WAIT) == 0) { + struct position_state_changed *pos_ev = new_position_state_changed(); + pos_ev->position = ev.position; + pos_ev->state = ev.state; + pos_ev->timestamp = ev.timestamp; + + LOG_DBG("Trigger key position state change for %d", ev.position); + ZMK_EVENT_RAISE(pos_ev); + } +} + +K_WORK_DEFINE(peripheral_event_work, peripheral_event_work_callback); + +static uint8_t split_central_notify_func(struct bt_conn *conn, struct bt_gatt_subscribe_params *params, + const void *data, uint16_t length) { static uint8_t position_state[POSITION_STATE_DATA_LEN]; uint8_t changed_positions[POSITION_STATE_DATA_LEN]; @@ -58,13 +81,11 @@ static uint8_t split_central_notify_func(struct bt_conn *conn, if (changed_positions[i] & BIT(j)) { uint32_t position = (i * 8) + j; bool pressed = position_state[i] & BIT(j); - struct position_state_changed *pos_ev = new_position_state_changed(); - pos_ev->position = position; - pos_ev->state = pressed; - pos_ev->timestamp = k_uptime_get(); + struct zmk_split_peripheral_event ev = { + .position = position, .state = pressed, .timestamp = k_uptime_get()}; - LOG_DBG("Trigger key position state change for %d", position); - ZMK_EVENT_RAISE(pos_ev); + k_msgq_put(&peripheral_event_msgq, &ev, K_NO_WAIT); + k_work_submit(&peripheral_event_work); } } } @@ -321,4 +342,4 @@ int zmk_split_bt_central_init(const struct device *_arg) { return start_scan(); } -SYS_INIT(zmk_split_bt_central_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); \ No newline at end of file +SYS_INIT(zmk_split_bt_central_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);