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 May 26, 2024
1 parent 4a29ed2 commit 638ae18
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 86 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);
5 changes: 5 additions & 0 deletions app/include/zmk/split/service.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ 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;
};

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/keymap.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,15 +214,15 @@ int zmk_keymap_apply_position_state(uint8_t source, int layer, uint32_t position
if (source == ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL) {
return invoke_locally(&binding, event, pressed);
} else {
return zmk_split_bt_invoke_behavior(source, &binding, event, pressed);
return zmk_split_invoke_behavior(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
95 changes: 13 additions & 82 deletions app/src/split/bluetooth/central.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,89 +713,24 @@ static struct bt_conn_cb conn_callbacks = {
.disconnected = split_central_disconnected,
};

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,
.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 @@ -836,11 +771,7 @@ int zmk_split_bt_update_hid_indicator(zmk_hid_indicators_t indicators) {
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)

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

return IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START) ? 0 : start_scanning();
}

Expand Down
77 changes: 77 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,76 @@ 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,
.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 638ae18

Please sign in to comment.