Skip to content

Commit

Permalink
refactor(split): move central split run out of Bluetooth directory
Browse files Browse the repository at this point in the history
  • Loading branch information
xudongzheng committed Dec 11, 2024
1 parent b0c0341 commit 04c4e00
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 88 deletions.
4 changes: 2 additions & 2 deletions app/include/zmk/split/bluetooth/central.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
#include <zmk/hid_indicators_types.h>
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)

int zmk_split_bt_invoke_behavior(uint8_t source, struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event, bool state);
int zmk_split_invoke_behavior(uint8_t source, struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event, bool state);

#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)

Expand Down
3 changes: 3 additions & 0 deletions app/include/zmk/split/central.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@

#include <zmk/events/position_state_changed.h>
#include <zmk/events/sensor_event.h>
#include <zmk/split/service.h>

void zmk_position_state_change_handle(struct zmk_position_state_changed *ev);

#if ZMK_KEYMAP_HAS_SENSORS
void zmk_sensor_event_handle(struct zmk_sensor_event *ev);
#endif

void send_split_run_impl(struct zmk_split_run_behavior_payload_wrapper *payload_wrapper);
6 changes: 5 additions & 1 deletion app/include/zmk/split/service.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,18 @@ struct zmk_split_run_behavior_payload {
char behavior_dev[ZMK_SPLIT_RUN_BEHAVIOR_DEV_LEN];
} __packed;

struct zmk_split_run_behavior_payload_wrapper {
uint8_t source;
struct zmk_split_run_behavior_payload payload;
};

struct zmk_split_input_event_payload {
uint8_t type;
uint16_t code;
uint32_t value;
uint8_t sync;
} __packed;


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,
Expand Down
4 changes: 2 additions & 2 deletions app/src/behavior.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,15 @@ int zmk_behavior_invoke_binding(const struct zmk_behavior_binding *src_binding,
if (event.source == ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL) {
return invoke_locally(&binding, event, pressed);
} else {
return zmk_split_bt_invoke_behavior(event.source, &binding, event, pressed);
return zmk_split_invoke_behavior(event.source, &binding, event, pressed);
}
#else
return invoke_locally(&binding, event, pressed);
#endif
case BEHAVIOR_LOCALITY_GLOBAL:
#if ZMK_BLE_IS_CENTRAL
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
return invoke_locally(&binding, event, pressed);
Expand Down
97 changes: 14 additions & 83 deletions app/src/split/bluetooth/central.c
Original file line number Diff line number Diff line change
Expand Up @@ -991,90 +991,24 @@ static struct bt_conn_cb conn_callbacks = {
.security_changed = split_central_security_changed,
};

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;

struct zmk_split_run_behavior_payload_wrapper {
uint8_t source;
struct zmk_split_run_behavior_payload payload;
};

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);
}
void send_split_run_impl(struct zmk_split_run_behavior_payload_wrapper *payload_wrapper) {
if (peripherals[payload_wrapper->source].state != PERIPHERAL_SLOT_STATE_CONNECTED) {
LOG_ERR("Source not connected");
return;
}
if (!peripherals[payload_wrapper->source].run_behavior_handle) {
LOG_ERR("Run behavior handle not found");
return;
}
}

K_WORK_DEFINE(split_central_split_run_work, split_central_split_run_callback);

static int
split_bt_invoke_behavior_payload(struct zmk_split_run_behavior_payload_wrapper payload_wrapper) {
LOG_DBG("");
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);

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_bt_invoke_behavior_payload(payload_wrapper);
}
default:
LOG_WRN("Failed to queue behavior to send (%d)", err);
return err;
}
LOG_ERR("Failed to write the behavior characteristic (err %d)", 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,
.source = event.source,
.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)
Expand Down Expand Up @@ -1131,9 +1065,6 @@ static struct settings_handler ble_central_settings_handler = {
#endif // IS_ENABLED(CONFIG_SETTINGS)

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);

#if IS_ENABLED(CONFIG_SETTINGS)
Expand All @@ -1154,4 +1085,4 @@ static int zmk_split_bt_central_listener_cb(const zmk_event_t *eh) {
}

ZMK_LISTENER(zmk_split_bt_central, zmk_split_bt_central_listener_cb);
ZMK_SUBSCRIPTION(zmk_split_bt_central, zmk_physical_layout_selection_changed);
ZMK_SUBSCRIPTION(zmk_split_bt_central, zmk_physical_layout_selection_changed);
78 changes: 78 additions & 0 deletions app/src/split/central.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
#include <zephyr/types.h>
#include <zephyr/init.h>

#include <zmk/stdlib.h>
#include <zmk/behavior.h>
#include <zmk/event_manager.h>
#include <zmk/events/position_state_changed.h>
#include <zmk/events/sensor_event.h>
#include <zmk/split/central.h>
#include <zmk/split/service.h>

#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
Expand Down Expand Up @@ -51,3 +55,77 @@ void zmk_sensor_event_handle(struct zmk_sensor_event *ev) {
k_work_submit(&peripheral_sensor_event_work);
}
#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,
.source = event.source,
.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);

0 comments on commit 04c4e00

Please sign in to comment.