From 6411543ad7df6dcd4c1488f75adbae6fae34ac0e Mon Sep 17 00:00:00 2001 From: Xudong Zheng <7pkvm5aw@slicealias.com> Date: Sat, 23 Dec 2023 16:47:08 -0500 Subject: [PATCH] refactor(split): move peripheral service out of Bluetooth directory --- .../zmk/split/{bluetooth => }/service.h | 18 ++- app/src/pointing/input_split.c | 4 +- app/src/split/CMakeLists.txt | 1 + app/src/split/bluetooth/central.c | 2 +- app/src/split/bluetooth/service.c | 120 ++-------------- app/src/split/listener.c | 10 +- app/src/split/service.c | 128 ++++++++++++++++++ 7 files changed, 160 insertions(+), 123 deletions(-) rename app/include/zmk/split/{bluetooth => }/service.h (58%) create mode 100644 app/src/split/service.c diff --git a/app/include/zmk/split/bluetooth/service.h b/app/include/zmk/split/service.h similarity index 58% rename from app/include/zmk/split/bluetooth/service.h rename to app/include/zmk/split/service.h index 90e5dd7ee8e5..ccb259faafb1 100644 --- a/app/include/zmk/split/bluetooth/service.h +++ b/app/include/zmk/split/service.h @@ -10,6 +10,7 @@ #include #define ZMK_SPLIT_RUN_BEHAVIOR_DEV_LEN 9 +#define ZMK_SPLIT_POS_STATE_LEN 16 struct sensor_event { uint8_t sensor_index; @@ -38,10 +39,15 @@ struct zmk_split_input_event_payload { uint8_t sync; } __packed; -int zmk_split_bt_position_pressed(uint8_t position); -int zmk_split_bt_position_released(uint8_t position); -int zmk_split_bt_sensor_triggered(uint8_t sensor_index, - const struct zmk_sensor_channel_data channel_data[], - size_t channel_data_size); -int zmk_split_bt_report_input(uint8_t reg, uint8_t type, uint16_t code, int32_t value, bool sync); +int zmk_split_position_pressed(uint8_t position); +int zmk_split_position_released(uint8_t position); +int zmk_split_sensor_triggered(uint8_t sensor_index, + const struct zmk_sensor_channel_data channel_data[], + size_t channel_data_size); +int zmk_split_report_input(uint8_t reg, uint8_t type, uint16_t code, int32_t value, bool sync); + +void send_position_state_impl(uint8_t *state, int len); +#if ZMK_KEYMAP_HAS_SENSORS +void send_sensor_state_impl(struct sensor_event *event, int len); +#endif diff --git a/app/src/pointing/input_split.c b/app/src/pointing/input_split.c index 55a84ea46240..7efe3d3e6773 100644 --- a/app/src/pointing/input_split.c +++ b/app/src/pointing/input_split.c @@ -59,11 +59,11 @@ int zmk_input_split_report_peripheral_event(uint8_t reg, uint8_t type, uint16_t zmk_input_processor_handle_event(processors_##n[i].dev, evt, processors_##n[i].param1, \ processors_##n[i].param2, NULL); \ } \ - zmk_split_bt_report_input(DT_INST_REG_ADDR(n), evt->type, evt->code, evt->value, \ + zmk_split_report_input(DT_INST_REG_ADDR(n), evt->type, evt->code, evt->value, \ evt->sync); \ } \ INPUT_CALLBACK_DEFINE(DEVICE_DT_GET(DT_INST_PHANDLE(n, device)), split_input_handler_##n); #endif -DT_INST_FOREACH_STATUS_OKAY(ZIS_INST) \ No newline at end of file +DT_INST_FOREACH_STATUS_OKAY(ZIS_INST) diff --git a/app/src/split/CMakeLists.txt b/app/src/split/CMakeLists.txt index 2e243e5c92f8..1205c026f782 100644 --- a/app/src/split/CMakeLists.txt +++ b/app/src/split/CMakeLists.txt @@ -3,6 +3,7 @@ if (CONFIG_ZMK_SPLIT_BLE AND (NOT CONFIG_ZMK_SPLIT_ROLE_CENTRAL)) target_sources(app PRIVATE listener.c) + target_sources(app PRIVATE service.c) endif() if (CONFIG_ZMK_SPLIT_BLE) diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index 4c354b36b16c..c22d64e7496d 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -24,7 +24,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include -#include +#include #include #include #include diff --git a/app/src/split/bluetooth/service.c b/app/src/split/bluetooth/service.c index def883b0c085..92e4f251a2e8 100644 --- a/app/src/split/bluetooth/service.c +++ b/app/src/split/bluetooth/service.c @@ -22,7 +22,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include -#include +#include #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) #include @@ -45,10 +45,8 @@ static void split_svc_sensor_state_ccc(const struct bt_gatt_attr *attr, uint16_t } #endif /* ZMK_KEYMAP_HAS_SENSORS */ -#define POS_STATE_LEN 16 - static uint8_t num_of_positions = ZMK_KEYMAP_LEN; -static uint8_t position_state[POS_STATE_LEN]; +static uint8_t position_state[ZMK_SPLIT_POS_STATE_LEN]; static struct zmk_split_run_behavior_payload behavior_run_payload; @@ -244,112 +242,27 @@ BT_GATT_SERVICE_DEFINE( split_svc_get_selected_phys_layout, split_svc_select_phys_layout, NULL), ); -K_THREAD_STACK_DEFINE(service_q_stack, CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE); - -struct k_work_q service_work_q; - -K_MSGQ_DEFINE(position_state_msgq, sizeof(char[POS_STATE_LEN]), - CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE, 4); - -void send_position_state_callback(struct k_work *work) { - uint8_t state[POS_STATE_LEN]; - - while (k_msgq_get(&position_state_msgq, &state, K_NO_WAIT) == 0) { - int err = bt_gatt_notify(NULL, &split_svc.attrs[1], &state, sizeof(state)); - if (err) { - LOG_DBG("Error notifying %d", err); - } - } -}; - -K_WORK_DEFINE(service_position_notify_work, send_position_state_callback); - -int send_position_state() { - int err = k_msgq_put(&position_state_msgq, position_state, K_MSEC(100)); +void send_position_state_impl(uint8_t *state, int len) { + memcpy(position_state, state, MIN(len, sizeof(position_state))); + int err = bt_gatt_notify(NULL, &split_svc.attrs[1], state, len); if (err) { - switch (err) { - case -EAGAIN: { - LOG_WRN("Position state message queue full, popping first message and queueing again"); - uint8_t discarded_state[POS_STATE_LEN]; - k_msgq_get(&position_state_msgq, &discarded_state, K_NO_WAIT); - return send_position_state(); - } - default: - LOG_WRN("Failed to queue position state to send (%d)", err); - return err; - } + LOG_DBG("Error notifying %d", err); } - - k_work_submit_to_queue(&service_work_q, &service_position_notify_work); - - return 0; -} - -int zmk_split_bt_position_pressed(uint8_t position) { - WRITE_BIT(position_state[position / 8], position % 8, true); - return send_position_state(); -} - -int zmk_split_bt_position_released(uint8_t position) { - WRITE_BIT(position_state[position / 8], position % 8, false); - return send_position_state(); } #if ZMK_KEYMAP_HAS_SENSORS -K_MSGQ_DEFINE(sensor_state_msgq, sizeof(struct sensor_event), - CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE, 4); - -void send_sensor_state_callback(struct k_work *work) { - while (k_msgq_get(&sensor_state_msgq, &last_sensor_event, K_NO_WAIT) == 0) { - int err = bt_gatt_notify(NULL, &split_svc.attrs[8], &last_sensor_event, - sizeof(last_sensor_event)); - if (err) { - LOG_DBG("Error notifying %d", err); - } - } -}; - -K_WORK_DEFINE(service_sensor_notify_work, send_sensor_state_callback); - -int send_sensor_state(struct sensor_event ev) { - int err = k_msgq_put(&sensor_state_msgq, &ev, K_MSEC(100)); +void send_sensor_state_impl(struct sensor_event *event, int len) { + memcpy(&last_sensor_event, event, MIN(len, sizeof(last_sensor_event))); + int err = bt_gatt_notify(NULL, &split_svc.attrs[8], event, len); if (err) { - // retry... - switch (err) { - case -EAGAIN: { - LOG_WRN("Sensor state message queue full, popping first message and queueing again"); - struct sensor_event discarded_state; - k_msgq_get(&sensor_state_msgq, &discarded_state, K_NO_WAIT); - return send_sensor_state(ev); - } - default: - LOG_WRN("Failed to queue sensor state to send (%d)", err); - return err; - } + LOG_DBG("Error notifying %d", err); } - - k_work_submit_to_queue(&service_work_q, &service_sensor_notify_work); - return 0; -} - -int zmk_split_bt_sensor_triggered(uint8_t sensor_index, - const struct zmk_sensor_channel_data channel_data[], - size_t channel_data_size) { - if (channel_data_size > ZMK_SENSOR_EVENT_MAX_CHANNELS) { - return -EINVAL; - } - - struct sensor_event ev = - (struct sensor_event){.sensor_index = sensor_index, .channel_data_size = channel_data_size}; - memcpy(ev.channel_data, channel_data, - channel_data_size * sizeof(struct zmk_sensor_channel_data)); - return send_sensor_state(ev); } #endif /* ZMK_KEYMAP_HAS_SENSORS */ #if IS_ENABLED(CONFIG_ZMK_INPUT_SPLIT) -int zmk_split_bt_report_input(uint8_t reg, uint8_t type, uint16_t code, int32_t value, bool sync) { +int zmk_split_report_input(uint8_t reg, uint8_t type, uint16_t code, int32_t value, bool sync) { for (size_t i = 0; i < split_svc.attr_count; i++) { if (bt_uuid_cmp(split_svc.attrs[i].uuid, @@ -369,14 +282,3 @@ int zmk_split_bt_report_input(uint8_t reg, uint8_t type, uint16_t code, int32_t } #endif /* IS_ENABLED(CONFIG_ZMK_INPUT_SPLIT) */ - -static int service_init(void) { - static const struct k_work_queue_config queue_config = { - .name = "Split Peripheral Notification Queue"}; - k_work_queue_start(&service_work_q, service_q_stack, K_THREAD_STACK_SIZEOF(service_q_stack), - CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_PRIORITY, &queue_config); - - return 0; -} - -SYS_INIT(service_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); diff --git a/app/src/split/listener.c b/app/src/split/listener.c index 9b680d2c89cd..d7a144de57fa 100644 --- a/app/src/split/listener.c +++ b/app/src/split/listener.c @@ -7,7 +7,7 @@ #include #include -#include +#include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -23,17 +23,17 @@ int split_listener(const zmk_event_t *eh) { const struct zmk_position_state_changed *pos_ev; if ((pos_ev = as_zmk_position_state_changed(eh)) != NULL) { if (pos_ev->state) { - return zmk_split_bt_position_pressed(pos_ev->position); + return zmk_split_position_pressed(pos_ev->position); } else { - return zmk_split_bt_position_released(pos_ev->position); + return zmk_split_position_released(pos_ev->position); } } #if ZMK_KEYMAP_HAS_SENSORS const struct zmk_sensor_event *sensor_ev; if ((sensor_ev = as_zmk_sensor_event(eh)) != NULL) { - return zmk_split_bt_sensor_triggered(sensor_ev->sensor_index, sensor_ev->channel_data, - sensor_ev->channel_data_size); + return zmk_split_sensor_triggered(sensor_ev->sensor_index, sensor_ev->channel_data, + sensor_ev->channel_data_size); } #endif /* ZMK_KEYMAP_HAS_SENSORS */ return ZMK_EV_EVENT_BUBBLE; diff --git a/app/src/split/service.c b/app/src/split/service.c new file mode 100644 index 000000000000..d680ef2aa666 --- /dev/null +++ b/app/src/split/service.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include + +#include +#include +#include + +#include +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +static uint8_t position_state[ZMK_SPLIT_POS_STATE_LEN]; +#if ZMK_KEYMAP_HAS_SENSORS +static struct sensor_event last_sensor_event; +#endif + +K_THREAD_STACK_DEFINE(service_q_stack, CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE); + +struct k_work_q service_work_q; + +K_MSGQ_DEFINE(position_state_msgq, sizeof(char[ZMK_SPLIT_POS_STATE_LEN]), + CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE, 4); + +void send_position_state_callback(struct k_work *work) { + uint8_t state[ZMK_SPLIT_POS_STATE_LEN]; + + while (k_msgq_get(&position_state_msgq, &state, K_NO_WAIT) == 0) { + send_position_state_impl(state, sizeof(state)); + } +}; + +K_WORK_DEFINE(service_position_notify_work, send_position_state_callback); + +int send_position_state() { + int err = k_msgq_put(&position_state_msgq, position_state, K_MSEC(100)); + if (err) { + switch (err) { + case -EAGAIN: { + LOG_WRN("Position state message queue full, popping first message and queueing again"); + uint8_t discarded_state[ZMK_SPLIT_POS_STATE_LEN]; + k_msgq_get(&position_state_msgq, &discarded_state, K_NO_WAIT); + return send_position_state(); + } + default: + LOG_WRN("Failed to queue position state to send (%d)", err); + return err; + } + } + + k_work_submit_to_queue(&service_work_q, &service_position_notify_work); + + return 0; +} + +int zmk_split_position_pressed(uint8_t position) { + WRITE_BIT(position_state[position / 8], position % 8, true); + return send_position_state(); +} + +int zmk_split_position_released(uint8_t position) { + WRITE_BIT(position_state[position / 8], position % 8, false); + return send_position_state(); +} + +#if ZMK_KEYMAP_HAS_SENSORS +K_MSGQ_DEFINE(sensor_state_msgq, sizeof(struct sensor_event), + CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE, 4); + +void send_sensor_state_callback(struct k_work *work) { + while (k_msgq_get(&sensor_state_msgq, &last_sensor_event, K_NO_WAIT) == 0) { + send_sensor_state_impl(&last_sensor_event, sizeof(last_sensor_event)); + } +}; + +K_WORK_DEFINE(service_sensor_notify_work, send_sensor_state_callback); + +int send_sensor_state(struct sensor_event ev) { + int err = k_msgq_put(&sensor_state_msgq, &ev, K_MSEC(100)); + if (err) { + // retry... + switch (err) { + case -EAGAIN: { + LOG_WRN("Sensor state message queue full, popping first message and queueing again"); + struct sensor_event discarded_state; + k_msgq_get(&sensor_state_msgq, &discarded_state, K_NO_WAIT); + return send_sensor_state(ev); + } + default: + LOG_WRN("Failed to queue sensor state to send (%d)", err); + return err; + } + } + + k_work_submit_to_queue(&service_work_q, &service_sensor_notify_work); + return 0; +} + +int zmk_split_sensor_triggered(uint8_t sensor_index, + const struct zmk_sensor_channel_data channel_data[], + size_t channel_data_size) { + if (channel_data_size > ZMK_SENSOR_EVENT_MAX_CHANNELS) { + return -EINVAL; + } + + struct sensor_event ev = + (struct sensor_event){.sensor_index = sensor_index, .channel_data_size = channel_data_size}; + memcpy(ev.channel_data, channel_data, + channel_data_size * sizeof(struct zmk_sensor_channel_data)); + return send_sensor_state(ev); +} +#endif /* ZMK_KEYMAP_HAS_SENSORS */ + +static int service_init(void) { + static const struct k_work_queue_config queue_config = { + .name = "Split Peripheral Notification Queue"}; + k_work_queue_start(&service_work_q, service_q_stack, K_THREAD_STACK_SIZEOF(service_q_stack), + CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_PRIORITY, &queue_config); + + return 0; +} + +SYS_INIT(service_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);