refactor(split): move central split run out of Bluetooth directory

This commit is contained in:
Xudong Zheng 2023-12-30 12:27:47 -05:00
parent 264bdfbe14
commit 07bc3b6a9e
6 changed files with 102 additions and 85 deletions

View file

@ -8,8 +8,8 @@
#include <zmk/hid_indicators_types.h> #include <zmk/hid_indicators_types.h>
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
int zmk_split_bt_invoke_behavior(uint8_t source, struct zmk_behavior_binding *binding, int zmk_split_invoke_behavior(uint8_t source, struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event, bool state); struct zmk_behavior_binding_event event, bool state);
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)

View file

@ -8,9 +8,12 @@
#include <zmk/events/position_state_changed.h> #include <zmk/events/position_state_changed.h>
#include <zmk/events/sensor_event.h> #include <zmk/events/sensor_event.h>
#include <zmk/split/service.h>
void zmk_position_state_change_handle(struct zmk_position_state_changed *ev); void zmk_position_state_change_handle(struct zmk_position_state_changed *ev);
#if ZMK_KEYMAP_HAS_SENSORS #if ZMK_KEYMAP_HAS_SENSORS
void zmk_sensor_event_handle(struct zmk_sensor_event *ev); void zmk_sensor_event_handle(struct zmk_sensor_event *ev);
#endif #endif
void send_split_run_impl(struct zmk_split_run_behavior_payload_wrapper *payload_wrapper);

View file

@ -31,6 +31,11 @@ struct zmk_split_run_behavior_payload {
char behavior_dev[ZMK_SPLIT_RUN_BEHAVIOR_DEV_LEN]; char behavior_dev[ZMK_SPLIT_RUN_BEHAVIOR_DEV_LEN];
} __packed; } __packed;
struct zmk_split_run_behavior_payload_wrapper {
uint8_t source;
struct zmk_split_run_behavior_payload payload;
};
int zmk_split_position_pressed(uint8_t position); int zmk_split_position_pressed(uint8_t position);
int zmk_split_position_released(uint8_t position); int zmk_split_position_released(uint8_t position);
int zmk_split_sensor_triggered(uint8_t sensor_index, int zmk_split_sensor_triggered(uint8_t sensor_index,

View file

@ -214,7 +214,7 @@ int zmk_keymap_apply_position_state(uint8_t source, int layer, uint32_t position
if (source == ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL) { if (source == ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL) {
return invoke_locally(&binding, event, pressed); return invoke_locally(&binding, event, pressed);
} else { } else {
return zmk_split_bt_invoke_behavior(source, &binding, event, pressed); return zmk_split_invoke_behavior(source, &binding, event, pressed);
} }
#else #else
return invoke_locally(&binding, event, pressed); return invoke_locally(&binding, event, pressed);
@ -222,7 +222,7 @@ int zmk_keymap_apply_position_state(uint8_t source, int layer, uint32_t position
case BEHAVIOR_LOCALITY_GLOBAL: case BEHAVIOR_LOCALITY_GLOBAL:
#if ZMK_BLE_IS_CENTRAL #if ZMK_BLE_IS_CENTRAL
for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) { for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) {
zmk_split_bt_invoke_behavior(i, &binding, event, pressed); zmk_split_invoke_behavior(i, &binding, event, pressed);
} }
#endif #endif
return invoke_locally(&binding, event, pressed); return invoke_locally(&binding, event, pressed);

View file

@ -714,89 +714,24 @@ static struct bt_conn_cb conn_callbacks = {
.disconnected = split_central_disconnected, .disconnected = split_central_disconnected,
}; };
K_THREAD_STACK_DEFINE(split_central_split_run_q_stack, void send_split_run_impl(struct zmk_split_run_behavior_payload_wrapper *payload_wrapper) {
CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_STACK_SIZE); if (peripherals[payload_wrapper->source].state != PERIPHERAL_SLOT_STATE_CONNECTED) {
LOG_ERR("Source not connected");
struct k_work_q split_central_split_run_q; return;
}
struct zmk_split_run_behavior_payload_wrapper { if (!peripherals[payload_wrapper->source].run_behavior_handle) {
uint8_t source; LOG_ERR("Run behavior handle not found");
struct zmk_split_run_behavior_payload payload; return;
};
K_MSGQ_DEFINE(zmk_split_central_split_run_msgq,
sizeof(struct zmk_split_run_behavior_payload_wrapper),
CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_QUEUE_SIZE, 4);
void split_central_split_run_callback(struct k_work *work) {
struct zmk_split_run_behavior_payload_wrapper payload_wrapper;
LOG_DBG("");
while (k_msgq_get(&zmk_split_central_split_run_msgq, &payload_wrapper, K_NO_WAIT) == 0) {
if (peripherals[payload_wrapper.source].state != PERIPHERAL_SLOT_STATE_CONNECTED) {
LOG_ERR("Source not connected");
continue;
}
if (!peripherals[payload_wrapper.source].run_behavior_handle) {
LOG_ERR("Run behavior handle not found");
continue;
}
int err = bt_gatt_write_without_response(
peripherals[payload_wrapper.source].conn,
peripherals[payload_wrapper.source].run_behavior_handle, &payload_wrapper.payload,
sizeof(struct zmk_split_run_behavior_payload), true);
if (err) {
LOG_ERR("Failed to write the behavior characteristic (err %d)", err);
}
} }
}
K_WORK_DEFINE(split_central_split_run_work, split_central_split_run_callback); int err = bt_gatt_write_without_response(
peripherals[payload_wrapper->source].conn,
peripherals[payload_wrapper->source].run_behavior_handle, &payload_wrapper->payload,
sizeof(struct zmk_split_run_behavior_payload), true);
static int
split_bt_invoke_behavior_payload(struct zmk_split_run_behavior_payload_wrapper payload_wrapper) {
LOG_DBG("");
int err = k_msgq_put(&zmk_split_central_split_run_msgq, &payload_wrapper, K_MSEC(100));
if (err) { if (err) {
switch (err) { LOG_ERR("Failed to write the behavior characteristic (err %d)", err);
case -EAGAIN: {
LOG_WRN("Consumer message queue full, popping first message and queueing again");
struct zmk_split_run_behavior_payload_wrapper discarded_report;
k_msgq_get(&zmk_split_central_split_run_msgq, &discarded_report, K_NO_WAIT);
return split_bt_invoke_behavior_payload(payload_wrapper);
}
default:
LOG_WRN("Failed to queue behavior to send (%d)", err);
return err;
}
} }
k_work_submit_to_queue(&split_central_split_run_q, &split_central_split_run_work);
return 0;
};
int zmk_split_bt_invoke_behavior(uint8_t source, struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event, bool state) {
struct zmk_split_run_behavior_payload payload = {.data = {
.param1 = binding->param1,
.param2 = binding->param2,
.position = event.position,
.state = state ? 1 : 0,
}};
const size_t payload_dev_size = sizeof(payload.behavior_dev);
if (strlcpy(payload.behavior_dev, binding->behavior_dev, payload_dev_size) >=
payload_dev_size) {
LOG_ERR("Truncated behavior label %s to %s before invoking peripheral behavior",
binding->behavior_dev, payload.behavior_dev);
}
struct zmk_split_run_behavior_payload_wrapper wrapper = {.source = source, .payload = payload};
return split_bt_invoke_behavior_payload(wrapper);
} }
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
@ -853,9 +788,6 @@ static struct settings_handler ble_central_settings_handler = {
#endif // IS_ENABLED(CONFIG_SETTINGS) #endif // IS_ENABLED(CONFIG_SETTINGS)
static int zmk_split_bt_central_init(void) { static int zmk_split_bt_central_init(void) {
k_work_queue_start(&split_central_split_run_q, split_central_split_run_q_stack,
K_THREAD_STACK_SIZEOF(split_central_split_run_q_stack),
CONFIG_ZMK_BLE_THREAD_PRIORITY, NULL);
bt_conn_cb_register(&conn_callbacks); bt_conn_cb_register(&conn_callbacks);
#if IS_ENABLED(CONFIG_SETTINGS) #if IS_ENABLED(CONFIG_SETTINGS)

View file

@ -7,9 +7,13 @@
#include <zephyr/types.h> #include <zephyr/types.h>
#include <zephyr/init.h> #include <zephyr/init.h>
#include <zmk/stdlib.h>
#include <zmk/behavior.h>
#include <zmk/event_manager.h> #include <zmk/event_manager.h>
#include <zmk/events/position_state_changed.h> #include <zmk/events/position_state_changed.h>
#include <zmk/events/sensor_event.h> #include <zmk/events/sensor_event.h>
#include <zmk/split/central.h>
#include <zmk/split/service.h>
#include <zephyr/logging/log.h> #include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
@ -51,3 +55,76 @@ void zmk_sensor_event_handle(struct zmk_sensor_event *ev) {
k_work_submit(&peripheral_sensor_event_work); k_work_submit(&peripheral_sensor_event_work);
} }
#endif /* ZMK_KEYMAP_HAS_SENSORS */ #endif /* ZMK_KEYMAP_HAS_SENSORS */
K_THREAD_STACK_DEFINE(split_central_split_run_q_stack,
CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_STACK_SIZE);
struct k_work_q split_central_split_run_q;
K_MSGQ_DEFINE(zmk_split_central_split_run_msgq,
sizeof(struct zmk_split_run_behavior_payload_wrapper),
CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_QUEUE_SIZE, 4);
void split_central_split_run_callback(struct k_work *work) {
struct zmk_split_run_behavior_payload_wrapper payload_wrapper;
LOG_DBG("");
while (k_msgq_get(&zmk_split_central_split_run_msgq, &payload_wrapper, K_NO_WAIT) == 0) {
send_split_run_impl(&payload_wrapper);
}
}
K_WORK_DEFINE(split_central_split_run_work, split_central_split_run_callback);
static int
split_invoke_behavior_payload(struct zmk_split_run_behavior_payload_wrapper payload_wrapper) {
LOG_DBG("");
int err = k_msgq_put(&zmk_split_central_split_run_msgq, &payload_wrapper, K_MSEC(100));
if (err) {
switch (err) {
case -EAGAIN: {
LOG_WRN("Consumer message queue full, popping first message and queueing again");
struct zmk_split_run_behavior_payload_wrapper discarded_report;
k_msgq_get(&zmk_split_central_split_run_msgq, &discarded_report, K_NO_WAIT);
return split_invoke_behavior_payload(payload_wrapper);
}
default:
LOG_WRN("Failed to queue behavior to send (%d)", err);
return err;
}
}
k_work_submit_to_queue(&split_central_split_run_q, &split_central_split_run_work);
return 0;
};
int zmk_split_invoke_behavior(uint8_t source, struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event, bool state) {
struct zmk_split_run_behavior_payload payload = {.data = {
.param1 = binding->param1,
.param2 = binding->param2,
.position = event.position,
.state = state ? 1 : 0,
}};
const size_t payload_dev_size = sizeof(payload.behavior_dev);
if (strlcpy(payload.behavior_dev, binding->behavior_dev, payload_dev_size) >=
payload_dev_size) {
LOG_ERR("Truncated behavior label %s to %s before invoking peripheral behavior",
binding->behavior_dev, payload.behavior_dev);
}
struct zmk_split_run_behavior_payload_wrapper wrapper = {.source = source, .payload = payload};
return split_invoke_behavior_payload(wrapper);
}
static int zmk_split_central_init(void) {
k_work_queue_start(&split_central_split_run_q, split_central_split_run_q_stack,
K_THREAD_STACK_SIZEOF(split_central_split_run_q_stack),
CONFIG_ZMK_BLE_THREAD_PRIORITY, NULL);
return 0;
}
SYS_INIT(zmk_split_central_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);