Merge c0a3d490b0
into 7be955ff72
This commit is contained in:
commit
98c3c35cc6
15 changed files with 363 additions and 109 deletions
|
@ -89,6 +89,7 @@ target_sources_ifdef(CONFIG_ZMK_BATTERY_REPORTING app PRIVATE src/battery.c)
|
||||||
target_sources_ifdef(CONFIG_ZMK_HID_INDICATORS app PRIVATE src/events/hid_indicators_changed.c)
|
target_sources_ifdef(CONFIG_ZMK_HID_INDICATORS app PRIVATE src/events/hid_indicators_changed.c)
|
||||||
|
|
||||||
target_sources_ifdef(CONFIG_ZMK_SPLIT app PRIVATE src/events/split_peripheral_status_changed.c)
|
target_sources_ifdef(CONFIG_ZMK_SPLIT app PRIVATE src/events/split_peripheral_status_changed.c)
|
||||||
|
target_sources_ifdef(CONFIG_ZMK_SPLIT app PRIVATE src/events/split_data_xfer_event.c)
|
||||||
add_subdirectory(src/split)
|
add_subdirectory(src/split)
|
||||||
|
|
||||||
target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/usb.c)
|
target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/usb.c)
|
||||||
|
|
17
app/include/zmk/events/split_data_xfer_event.h
Normal file
17
app/include/zmk/events/split_data_xfer_event.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zmk/event_manager.h>
|
||||||
|
#include <zmk/split/bluetooth/service.h>
|
||||||
|
|
||||||
|
struct zmk_split_data_xfer_event {
|
||||||
|
struct zmk_split_data_xfer_data data_xfer;
|
||||||
|
};
|
||||||
|
|
||||||
|
ZMK_EVENT_DECLARE(zmk_split_data_xfer_event);
|
|
@ -3,22 +3,14 @@
|
||||||
|
|
||||||
#include <zephyr/bluetooth/addr.h>
|
#include <zephyr/bluetooth/addr.h>
|
||||||
#include <zmk/behavior.h>
|
#include <zmk/behavior.h>
|
||||||
|
#include <zmk/split/bluetooth/service.h>
|
||||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
|
||||||
#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,
|
int zmk_split_bt_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)
|
|
||||||
|
|
||||||
int zmk_split_bt_update_hid_indicator(zmk_hid_indicators_t indicators);
|
|
||||||
|
|
||||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING)
|
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING)
|
||||||
|
|
||||||
int zmk_split_get_peripheral_battery_level(uint8_t source, uint8_t *level);
|
int zmk_split_get_peripheral_battery_level(uint8_t source, uint8_t *level);
|
||||||
|
|
||||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING)
|
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING)
|
||||||
|
int zmk_split_central_send_data(enum data_tag, uint8_t data_size, uint8_t *data);
|
||||||
|
|
|
@ -10,6 +10,20 @@
|
||||||
#include <zmk/sensors.h>
|
#include <zmk/sensors.h>
|
||||||
|
|
||||||
#define ZMK_SPLIT_RUN_BEHAVIOR_DEV_LEN 9
|
#define ZMK_SPLIT_RUN_BEHAVIOR_DEV_LEN 9
|
||||||
|
#define ZMK_SPLIT_DATA_XFER_MAX_LEN 16
|
||||||
|
|
||||||
|
enum data_tag {
|
||||||
|
// RGB state
|
||||||
|
DATA_TAG_RGB_STATE,
|
||||||
|
// Backlight state
|
||||||
|
DATA_TAG_BACKLIGHT_STATE,
|
||||||
|
// HID indicators state
|
||||||
|
DATA_TAG_HID_INDICATORS_STATE,
|
||||||
|
// Keymap state
|
||||||
|
DATA_TAG_KEYMAP_STATE,
|
||||||
|
// Start of custom tags
|
||||||
|
DATA_TAG_CUSTOM_START,
|
||||||
|
};
|
||||||
|
|
||||||
struct sensor_event {
|
struct sensor_event {
|
||||||
uint8_t sensor_index;
|
uint8_t sensor_index;
|
||||||
|
@ -30,6 +44,12 @@ 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_data_xfer_data {
|
||||||
|
enum data_tag data_tag;
|
||||||
|
uint8_t data_size;
|
||||||
|
uint8_t data[ZMK_SPLIT_DATA_XFER_MAX_LEN];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
int zmk_split_bt_position_pressed(uint8_t position);
|
int zmk_split_bt_position_pressed(uint8_t position);
|
||||||
int zmk_split_bt_position_released(uint8_t position);
|
int zmk_split_bt_position_released(uint8_t position);
|
||||||
int zmk_split_bt_sensor_triggered(uint8_t sensor_index,
|
int zmk_split_bt_sensor_triggered(uint8_t sensor_index,
|
||||||
|
|
|
@ -17,4 +17,4 @@
|
||||||
#define ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000001)
|
#define ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000001)
|
||||||
#define ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID ZMK_BT_SPLIT_UUID(0x00000002)
|
#define ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID ZMK_BT_SPLIT_UUID(0x00000002)
|
||||||
#define ZMK_SPLIT_BT_CHAR_SENSOR_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000003)
|
#define ZMK_SPLIT_BT_CHAR_SENSOR_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000003)
|
||||||
#define ZMK_SPLIT_BT_UPDATE_HID_INDICATORS_UUID ZMK_BT_SPLIT_UUID(0x00000004)
|
#define ZMK_SPLIT_BT_CHAR_DATA_XFER_UUID ZMK_BT_SPLIT_UUID(0x00000004)
|
||||||
|
|
|
@ -16,9 +16,19 @@
|
||||||
#include <zmk/activity.h>
|
#include <zmk/activity.h>
|
||||||
#include <zmk/backlight.h>
|
#include <zmk/backlight.h>
|
||||||
#include <zmk/usb.h>
|
#include <zmk/usb.h>
|
||||||
|
#include <zmk/ble.h>
|
||||||
#include <zmk/event_manager.h>
|
#include <zmk/event_manager.h>
|
||||||
#include <zmk/events/activity_state_changed.h>
|
#include <zmk/events/activity_state_changed.h>
|
||||||
#include <zmk/events/usb_conn_state_changed.h>
|
#include <zmk/events/usb_conn_state_changed.h>
|
||||||
|
#include <zmk/events/split_peripheral_status_changed.h>
|
||||||
|
#include <zmk/workqueue.h>
|
||||||
|
|
||||||
|
// Pull data sending framework if central, data receiving eventt if peripheral(s)
|
||||||
|
#if ZMK_BLE_IS_CENTRAL
|
||||||
|
#include <zmk/split/bluetooth/central.h>
|
||||||
|
#elif IS_ENABLED(CONFIG_ZMK_SPLIT)
|
||||||
|
#include <zmk/events/split_data_xfer_event.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
@ -42,7 +52,25 @@ struct backlight_state {
|
||||||
static struct backlight_state state = {.brightness = CONFIG_ZMK_BACKLIGHT_BRT_START,
|
static struct backlight_state state = {.brightness = CONFIG_ZMK_BACKLIGHT_BRT_START,
|
||||||
.on = IS_ENABLED(CONFIG_ZMK_BACKLIGHT_ON_START)};
|
.on = IS_ENABLED(CONFIG_ZMK_BACKLIGHT_ON_START)};
|
||||||
|
|
||||||
|
#if ZMK_BLE_IS_CENTRAL
|
||||||
|
|
||||||
|
static void zmk_backlight_send_state(struct k_work *work) {
|
||||||
|
LOG_HEXDUMP_DBG(&state, sizeof(struct backlight_state), "backlight state");
|
||||||
|
int err = zmk_split_central_send_data(DATA_TAG_BACKLIGHT_STATE, sizeof(struct backlight_state),
|
||||||
|
(uint8_t *)&state);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("send failed (err %d)", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
K_WORK_DEFINE(backlight_send_state_work, zmk_backlight_send_state);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static int zmk_backlight_update(void) {
|
static int zmk_backlight_update(void) {
|
||||||
|
#if ZMK_BLE_IS_CENTRAL
|
||||||
|
k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &backlight_send_state_work);
|
||||||
|
#endif
|
||||||
uint8_t brt = zmk_backlight_get_brt();
|
uint8_t brt = zmk_backlight_get_brt();
|
||||||
LOG_DBG("Update backlight brightness: %d%%", brt);
|
LOG_DBG("Update backlight brightness: %d%%", brt);
|
||||||
|
|
||||||
|
@ -157,7 +185,10 @@ static int backlight_auto_state(bool *prev_state, bool new_state) {
|
||||||
*prev_state = !new_state;
|
*prev_state = !new_state;
|
||||||
return zmk_backlight_update();
|
return zmk_backlight_update();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE) || \
|
||||||
|
IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB) || ZMK_BLE_IS_CENTRAL
|
||||||
static int backlight_event_listener(const zmk_event_t *eh) {
|
static int backlight_event_listener(const zmk_event_t *eh) {
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE)
|
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE)
|
||||||
|
@ -174,12 +205,19 @@ static int backlight_event_listener(const zmk_event_t *eh) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ZMK_BLE_IS_CENTRAL
|
||||||
|
if (as_zmk_split_peripheral_status_changed(eh)) {
|
||||||
|
// TODO: Have this only update when connected
|
||||||
|
k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &backlight_send_state_work);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMK_LISTENER(backlight, backlight_event_listener);
|
ZMK_LISTENER(backlight, backlight_event_listener);
|
||||||
#endif // IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE) ||
|
#endif // IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE) ||
|
||||||
// IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB)
|
// IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB) || ZMK_BLE_IS_CENTRAL
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE)
|
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE)
|
||||||
ZMK_SUBSCRIPTION(backlight, zmk_activity_state_changed);
|
ZMK_SUBSCRIPTION(backlight, zmk_activity_state_changed);
|
||||||
|
@ -189,4 +227,27 @@ ZMK_SUBSCRIPTION(backlight, zmk_activity_state_changed);
|
||||||
ZMK_SUBSCRIPTION(backlight, zmk_usb_conn_state_changed);
|
ZMK_SUBSCRIPTION(backlight, zmk_usb_conn_state_changed);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ZMK_BLE_IS_CENTRAL
|
||||||
|
ZMK_SUBSCRIPTION(backlight, zmk_split_peripheral_status_changed);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_SPLIT) && !IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||||
|
|
||||||
|
static int backlight_data_event_listener(const zmk_event_t *eh) {
|
||||||
|
const struct zmk_split_data_xfer_event *ev = as_zmk_split_data_xfer_event(eh);
|
||||||
|
if (ev->data_xfer.data_tag == DATA_TAG_BACKLIGHT_STATE) {
|
||||||
|
LOG_DBG("Backlight Data received of size: %d", ev->data_xfer.data_size);
|
||||||
|
LOG_HEXDUMP_DBG(ev->data_xfer.data, sizeof(struct zmk_split_data_xfer_event),
|
||||||
|
"received event:");
|
||||||
|
memcpy(&state, ev->data_xfer.data, sizeof(struct backlight_state));
|
||||||
|
LOG_HEXDUMP_DBG(&state, sizeof(struct backlight_state), "backlight state");
|
||||||
|
zmk_backlight_update_and_save();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZMK_LISTENER(backlight_data, backlight_data_event_listener);
|
||||||
|
ZMK_SUBSCRIPTION(backlight_data, zmk_split_data_xfer_event);
|
||||||
|
#endif
|
||||||
|
|
||||||
SYS_INIT(zmk_backlight_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
SYS_INIT(zmk_backlight_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||||
|
|
|
@ -88,7 +88,7 @@ static const struct behavior_driver_api behavior_backlight_driver_api = {
|
||||||
on_keymap_binding_convert_central_state_dependent_params,
|
on_keymap_binding_convert_central_state_dependent_params,
|
||||||
.binding_pressed = on_keymap_binding_pressed,
|
.binding_pressed = on_keymap_binding_pressed,
|
||||||
.binding_released = on_keymap_binding_released,
|
.binding_released = on_keymap_binding_released,
|
||||||
.locality = BEHAVIOR_LOCALITY_GLOBAL,
|
.locality = BEHAVIOR_LOCALITY_CENTRAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
BEHAVIOR_DT_INST_DEFINE(0, behavior_backlight_init, NULL, NULL, NULL, POST_KERNEL,
|
BEHAVIOR_DT_INST_DEFINE(0, behavior_backlight_init, NULL, NULL, NULL, POST_KERNEL,
|
||||||
|
|
|
@ -146,7 +146,7 @@ static const struct behavior_driver_api behavior_rgb_underglow_driver_api = {
|
||||||
on_keymap_binding_convert_central_state_dependent_params,
|
on_keymap_binding_convert_central_state_dependent_params,
|
||||||
.binding_pressed = on_keymap_binding_pressed,
|
.binding_pressed = on_keymap_binding_pressed,
|
||||||
.binding_released = on_keymap_binding_released,
|
.binding_released = on_keymap_binding_released,
|
||||||
.locality = BEHAVIOR_LOCALITY_GLOBAL,
|
.locality = BEHAVIOR_LOCALITY_CENTRAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
BEHAVIOR_DT_INST_DEFINE(0, behavior_rgb_underglow_init, NULL, NULL, NULL, POST_KERNEL,
|
BEHAVIOR_DT_INST_DEFINE(0, behavior_rgb_underglow_init, NULL, NULL, NULL, POST_KERNEL,
|
||||||
|
|
10
app/src/events/split_data_xfer_event.c
Normal file
10
app/src/events/split_data_xfer_event.c
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zmk/events/split_data_xfer_event.h>
|
||||||
|
|
||||||
|
ZMK_EVENT_IMPL(zmk_split_data_xfer_event);
|
|
@ -13,6 +13,8 @@
|
||||||
#include <zmk/events/hid_indicators_changed.h>
|
#include <zmk/events/hid_indicators_changed.h>
|
||||||
#include <zmk/events/endpoint_changed.h>
|
#include <zmk/events/endpoint_changed.h>
|
||||||
#include <zmk/split/bluetooth/central.h>
|
#include <zmk/split/bluetooth/central.h>
|
||||||
|
#include <zmk/events/split_peripheral_status_changed.h>
|
||||||
|
#include <zmk/workqueue.h>
|
||||||
|
|
||||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
@ -27,14 +29,23 @@ zmk_hid_indicators_t zmk_hid_indicators_get_profile(struct zmk_endpoint_instance
|
||||||
return hid_indicators[profile];
|
return hid_indicators[profile];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void zmk_hid_indicators_send_state(struct k_work *work) {
|
||||||
|
zmk_hid_indicators_t indicators = zmk_hid_indicators_get_current_profile();
|
||||||
|
int err = zmk_split_central_send_data(DATA_TAG_HID_INDICATORS_STATE,
|
||||||
|
sizeof(zmk_hid_indicators_t), (uint8_t *)&indicators);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("HID indicators send failed (err %d)", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
K_WORK_DEFINE(hid_indicators_send_state_work, zmk_hid_indicators_send_state);
|
||||||
|
|
||||||
static void raise_led_changed_event(struct k_work *_work) {
|
static void raise_led_changed_event(struct k_work *_work) {
|
||||||
const zmk_hid_indicators_t indicators = zmk_hid_indicators_get_current_profile();
|
const zmk_hid_indicators_t indicators = zmk_hid_indicators_get_current_profile();
|
||||||
|
|
||||||
raise_zmk_hid_indicators_changed((struct zmk_hid_indicators_changed){.indicators = indicators});
|
raise_zmk_hid_indicators_changed((struct zmk_hid_indicators_changed){.indicators = indicators});
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) && IS_ENABLED(CONFIG_ZMK_SPLIT_BLE)
|
k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &hid_indicators_send_state_work);
|
||||||
zmk_split_bt_update_hid_indicator(indicators);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static K_WORK_DEFINE(led_changed_work, raise_led_changed_event);
|
static K_WORK_DEFINE(led_changed_work, raise_led_changed_event);
|
||||||
|
@ -60,9 +71,14 @@ void zmk_hid_indicators_process_report(struct zmk_hid_led_report_body *report,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int profile_listener(const zmk_event_t *eh) {
|
static int profile_listener(const zmk_event_t *eh) {
|
||||||
|
if (as_zmk_endpoint_changed(eh)) {
|
||||||
raise_led_changed_event(NULL);
|
raise_led_changed_event(NULL);
|
||||||
|
} else if (as_zmk_split_peripheral_status_changed(eh)) {
|
||||||
|
k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &hid_indicators_send_state_work);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZMK_LISTENER(profile_listener, profile_listener);
|
static ZMK_LISTENER(profile_listener, profile_listener);
|
||||||
static ZMK_SUBSCRIPTION(profile_listener, zmk_endpoint_changed);
|
static ZMK_SUBSCRIPTION(profile_listener, zmk_endpoint_changed);
|
||||||
|
static ZMK_SUBSCRIPTION(profile_listener, zmk_split_peripheral_status_changed);
|
||||||
|
|
|
@ -97,10 +97,14 @@ static inline int set_layer_state(uint8_t layer, bool state) {
|
||||||
// Don't send state changes unless there was an actual change
|
// Don't send state changes unless there was an actual change
|
||||||
if (old_state != _zmk_keymap_layer_state) {
|
if (old_state != _zmk_keymap_layer_state) {
|
||||||
LOG_DBG("layer_changed: layer %d state %d", layer, state);
|
LOG_DBG("layer_changed: layer %d state %d", layer, state);
|
||||||
ret = raise_layer_state_changed(layer, state);
|
raise_layer_state_changed(layer, state);
|
||||||
if (ret < 0) {
|
#if ZMK_BLE_IS_CENTRAL
|
||||||
LOG_WRN("Failed to raise layer state changed (%d)", ret);
|
int err = zmk_split_central_send_data(DATA_TAG_KEYMAP_STATE, sizeof(uint32_t),
|
||||||
|
(uint8_t *)&_zmk_keymap_layer_state);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Keymap send failed (err %d)", err);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -21,11 +21,20 @@
|
||||||
|
|
||||||
#include <zmk/activity.h>
|
#include <zmk/activity.h>
|
||||||
#include <zmk/usb.h>
|
#include <zmk/usb.h>
|
||||||
|
#include <zmk/ble.h>
|
||||||
#include <zmk/event_manager.h>
|
#include <zmk/event_manager.h>
|
||||||
#include <zmk/events/activity_state_changed.h>
|
#include <zmk/events/activity_state_changed.h>
|
||||||
#include <zmk/events/usb_conn_state_changed.h>
|
#include <zmk/events/usb_conn_state_changed.h>
|
||||||
|
#include <zmk/events/split_peripheral_status_changed.h>
|
||||||
#include <zmk/workqueue.h>
|
#include <zmk/workqueue.h>
|
||||||
|
|
||||||
|
// Pull data sending framework if central, data receiving event if peripheral(s)
|
||||||
|
#if ZMK_BLE_IS_CENTRAL
|
||||||
|
#include <zmk/split/bluetooth/central.h>
|
||||||
|
#elif IS_ENABLED(CONFIG_ZMK_SPLIT)
|
||||||
|
#include <zmk/events/split_data_xfer_event.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
#if !DT_HAS_CHOSEN(zmk_underglow)
|
#if !DT_HAS_CHOSEN(zmk_underglow)
|
||||||
|
@ -130,6 +139,21 @@ static struct led_rgb hsb_to_rgb(struct zmk_led_hsb hsb) {
|
||||||
return rgb;
|
return rgb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ZMK_BLE_IS_CENTRAL
|
||||||
|
|
||||||
|
static void zmk_rgb_send_state(struct k_work *work) {
|
||||||
|
LOG_HEXDUMP_DBG(&state, sizeof(struct rgb_underglow_state), "RGB state");
|
||||||
|
int err = zmk_split_central_send_data(DATA_TAG_RGB_STATE, sizeof(struct rgb_underglow_state),
|
||||||
|
(uint8_t *)&state);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("send failed (err %d)", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
K_WORK_DEFINE(rgb_send_state_work, zmk_rgb_send_state);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static void zmk_rgb_underglow_effect_solid(void) {
|
static void zmk_rgb_underglow_effect_solid(void) {
|
||||||
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
|
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
|
||||||
pixels[i] = hsb_to_rgb(hsb_scale_min_max(state.color));
|
pixels[i] = hsb_to_rgb(hsb_scale_min_max(state.color));
|
||||||
|
@ -191,6 +215,14 @@ static void zmk_rgb_underglow_tick(struct k_work *work) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ZMK_BLE_IS_CENTRAL
|
||||||
|
// Every time the counter rolls to 1 synchronise the animations (If it was 0 then it constantly
|
||||||
|
// syncs when effect is a solid color)
|
||||||
|
if (state.animation_step == 1) {
|
||||||
|
k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &rgb_send_state_work);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int err = led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS);
|
int err = led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
LOG_ERR("Failed to update the RGB strip (%d)", err);
|
LOG_ERR("Failed to update the RGB strip (%d)", err);
|
||||||
|
@ -278,7 +310,9 @@ static int zmk_rgb_underglow_init(void) {
|
||||||
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB)
|
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB)
|
||||||
state.on = zmk_usb_is_powered();
|
state.on = zmk_usb_is_powered();
|
||||||
#endif
|
#endif
|
||||||
|
#if ZMK_BLE_IS_CENTRAL
|
||||||
|
k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &rgb_send_state_work);
|
||||||
|
#endif
|
||||||
if (state.on) {
|
if (state.on) {
|
||||||
k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50));
|
k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50));
|
||||||
}
|
}
|
||||||
|
@ -287,6 +321,10 @@ static int zmk_rgb_underglow_init(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int zmk_rgb_underglow_save_state(void) {
|
int zmk_rgb_underglow_save_state(void) {
|
||||||
|
// Send new state to peripheral when anything changes
|
||||||
|
#if ZMK_BLE_IS_CENTRAL
|
||||||
|
k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &rgb_send_state_work);
|
||||||
|
#endif
|
||||||
#if IS_ENABLED(CONFIG_SETTINGS)
|
#if IS_ENABLED(CONFIG_SETTINGS)
|
||||||
int ret = k_work_reschedule(&underglow_save_work, K_MSEC(CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE));
|
int ret = k_work_reschedule(&underglow_save_work, K_MSEC(CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE));
|
||||||
return MIN(ret, 0);
|
return MIN(ret, 0);
|
||||||
|
@ -319,7 +357,6 @@ int zmk_rgb_underglow_on(void) {
|
||||||
state.on = true;
|
state.on = true;
|
||||||
state.animation_step = 0;
|
state.animation_step = 0;
|
||||||
k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50));
|
k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50));
|
||||||
|
|
||||||
return zmk_rgb_underglow_save_state();
|
return zmk_rgb_underglow_save_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,8 +533,12 @@ static int rgb_underglow_auto_state(bool target_wake_state) {
|
||||||
return zmk_rgb_underglow_off();
|
return zmk_rgb_underglow_off();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int rgb_underglow_event_listener(const zmk_event_t *eh) {
|
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE) || \
|
||||||
|
IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB) || ZMK_BLE_IS_CENTRAL
|
||||||
|
|
||||||
|
static int rgb_underglow_activity_event_listener(const zmk_event_t *eh) {
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE)
|
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE)
|
||||||
if (as_zmk_activity_state_changed(eh)) {
|
if (as_zmk_activity_state_changed(eh)) {
|
||||||
|
@ -511,19 +552,57 @@ static int rgb_underglow_event_listener(const zmk_event_t *eh) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ZMK_BLE_IS_CENTRAL
|
||||||
|
if (as_zmk_split_peripheral_status_changed(eh)) {
|
||||||
|
// TODO: Have this only update when connected
|
||||||
|
k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &rgb_send_state_work);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMK_LISTENER(rgb_underglow, rgb_underglow_event_listener);
|
ZMK_LISTENER(rgb_underglow_activity, rgb_underglow_activity_event_listener);
|
||||||
#endif // IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE) ||
|
#endif // IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE) ||
|
||||||
// IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB)
|
// IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB) || ZMK_BLE_IS_CENTRAL
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE)
|
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE)
|
||||||
ZMK_SUBSCRIPTION(rgb_underglow, zmk_activity_state_changed);
|
ZMK_SUBSCRIPTION(rgb_underglow_activity, zmk_activity_state_changed);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB)
|
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB)
|
||||||
ZMK_SUBSCRIPTION(rgb_underglow, zmk_usb_conn_state_changed);
|
ZMK_SUBSCRIPTION(rgb_underglow_activity, zmk_usb_conn_state_changed);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ZMK_BLE_IS_CENTRAL
|
||||||
|
ZMK_SUBSCRIPTION(rgb_underglow_activity, zmk_split_peripheral_status_changed);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_SPLIT) && !IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||||
|
|
||||||
|
static int rgb_underglow_data_event_listener(const zmk_event_t *eh) {
|
||||||
|
const struct zmk_split_data_xfer_event *ev = as_zmk_split_data_xfer_event(eh);
|
||||||
|
if (ev->data_xfer.data_tag == DATA_TAG_RGB_STATE) {
|
||||||
|
LOG_DBG("RGB Data received of size: %d", ev->data_xfer.data_size);
|
||||||
|
// Should the RGB timer be stopped and started during this operation to keep state safe?
|
||||||
|
LOG_HEXDUMP_DBG(ev->data_xfer.data, sizeof(struct zmk_split_data_xfer_event),
|
||||||
|
"received event:");
|
||||||
|
static bool prev_state = false;
|
||||||
|
memcpy(&state, ev->data_xfer.data, sizeof(struct rgb_underglow_state));
|
||||||
|
LOG_HEXDUMP_DBG(&state, sizeof(struct rgb_underglow_state), "RGB state");
|
||||||
|
LOG_DBG("new on_state %d", state.on);
|
||||||
|
if (prev_state && !state.on) {
|
||||||
|
zmk_rgb_underglow_off();
|
||||||
|
} else if (!prev_state && state.on) {
|
||||||
|
zmk_rgb_underglow_on();
|
||||||
|
}
|
||||||
|
prev_state = state.on;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZMK_LISTENER(rgb_underglow_data, rgb_underglow_data_event_listener);
|
||||||
|
ZMK_SUBSCRIPTION(rgb_underglow_data, zmk_split_data_xfer_event);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SYS_INIT(zmk_rgb_underglow_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
SYS_INIT(zmk_rgb_underglow_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||||
|
|
|
@ -58,6 +58,14 @@ config ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_QUEUE_SIZE
|
||||||
int "Max number of behavior run events to queue to send to the peripheral(s)"
|
int "Max number of behavior run events to queue to send to the peripheral(s)"
|
||||||
default 5
|
default 5
|
||||||
|
|
||||||
|
config ZMK_SPLIT_BLE_CENTRAL_DATA_XFER_STACK_SIZE
|
||||||
|
int "BLE split central to peripheral thread stack size"
|
||||||
|
default 512
|
||||||
|
|
||||||
|
config ZMK_SPLIT_BLE_CENTRAL_DATA_XFER_QUEUE_SIZE
|
||||||
|
int "Max number of data transfer requests to queue to send to the peripheral(s)"
|
||||||
|
default 5
|
||||||
|
|
||||||
config ZMK_SPLIT_BLE_PREF_INT
|
config ZMK_SPLIT_BLE_PREF_INT
|
||||||
int "Connection interval to use for split central/peripheral connection"
|
int "Connection interval to use for split central/peripheral connection"
|
||||||
default 6
|
default 6
|
||||||
|
|
|
@ -28,7 +28,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
#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/events/battery_state_changed.h>
|
#include <zmk/events/battery_state_changed.h>
|
||||||
#include <zmk/hid_indicators_types.h>
|
#include <zmk/events/split_peripheral_status_changed.h>
|
||||||
|
|
||||||
static int start_scanning(void);
|
static int start_scanning(void);
|
||||||
|
|
||||||
|
@ -52,9 +52,7 @@ struct peripheral_slot {
|
||||||
struct bt_gatt_subscribe_params batt_lvl_subscribe_params;
|
struct bt_gatt_subscribe_params batt_lvl_subscribe_params;
|
||||||
struct bt_gatt_read_params batt_lvl_read_params;
|
struct bt_gatt_read_params batt_lvl_read_params;
|
||||||
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) */
|
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) */
|
||||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
uint16_t data_xfer_handle;
|
||||||
uint16_t update_hid_indicators;
|
|
||||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
|
||||||
uint8_t position_state[POSITION_STATE_DATA_LEN];
|
uint8_t position_state[POSITION_STATE_DATA_LEN];
|
||||||
uint8_t changed_positions[POSITION_STATE_DATA_LEN];
|
uint8_t changed_positions[POSITION_STATE_DATA_LEN];
|
||||||
};
|
};
|
||||||
|
@ -140,9 +138,7 @@ int release_peripheral_slot(int index) {
|
||||||
// Clean up previously discovered handles;
|
// Clean up previously discovered handles;
|
||||||
slot->subscribe_params.value_handle = 0;
|
slot->subscribe_params.value_handle = 0;
|
||||||
slot->run_behavior_handle = 0;
|
slot->run_behavior_handle = 0;
|
||||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
slot->data_xfer_handle = 0;
|
||||||
slot->update_hid_indicators = 0;
|
|
||||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -441,12 +437,29 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn,
|
||||||
slot->discover_params.uuid = NULL;
|
slot->discover_params.uuid = NULL;
|
||||||
slot->discover_params.start_handle = attr->handle + 2;
|
slot->discover_params.start_handle = attr->handle + 2;
|
||||||
slot->run_behavior_handle = bt_gatt_attr_value_handle(attr);
|
slot->run_behavior_handle = bt_gatt_attr_value_handle(attr);
|
||||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING)
|
||||||
} else if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid,
|
} else if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid,
|
||||||
BT_UUID_DECLARE_128(ZMK_SPLIT_BT_UPDATE_HID_INDICATORS_UUID))) {
|
BT_UUID_BAS_BATTERY_LEVEL)) {
|
||||||
LOG_DBG("Found update HID indicators handle");
|
LOG_DBG("Found battery level characteristics");
|
||||||
slot->update_hid_indicators = bt_gatt_attr_value_handle(attr);
|
slot->batt_lvl_subscribe_params.disc_params = &slot->sub_discover_params;
|
||||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
slot->batt_lvl_subscribe_params.end_handle = slot->discover_params.end_handle;
|
||||||
|
slot->batt_lvl_subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
|
||||||
|
slot->batt_lvl_subscribe_params.notify = split_central_battery_level_notify_func;
|
||||||
|
slot->batt_lvl_subscribe_params.value = BT_GATT_CCC_NOTIFY;
|
||||||
|
split_central_subscribe(conn, &slot->batt_lvl_subscribe_params);
|
||||||
|
|
||||||
|
slot->batt_lvl_read_params.func = split_central_battery_level_read_func;
|
||||||
|
slot->batt_lvl_read_params.handle_count = 1;
|
||||||
|
slot->batt_lvl_read_params.single.handle = bt_gatt_attr_value_handle(attr);
|
||||||
|
slot->batt_lvl_read_params.single.offset = 0;
|
||||||
|
bt_gatt_read(conn, &slot->batt_lvl_read_params);
|
||||||
|
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) */
|
||||||
|
} else if (bt_uuid_cmp(chrc_uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_DATA_XFER_UUID)) == 0) {
|
||||||
|
LOG_DBG("Found data transfer handle");
|
||||||
|
slot->discover_params.uuid = NULL;
|
||||||
|
slot->discover_params.start_handle = attr->handle + 2;
|
||||||
|
slot->data_xfer_handle = bt_gatt_attr_value_handle(attr);
|
||||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING)
|
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING)
|
||||||
} else if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid,
|
} else if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid,
|
||||||
BT_UUID_BAS_BATTERY_LEVEL)) {
|
BT_UUID_BAS_BATTERY_LEVEL)) {
|
||||||
|
@ -466,15 +479,12 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn,
|
||||||
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) */
|
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) */
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subscribed = slot->run_behavior_handle && slot->subscribe_params.value_handle;
|
bool subscribed =
|
||||||
|
slot->run_behavior_handle && slot->data_xfer_handle && slot->subscribe_params.value_handle;
|
||||||
#if ZMK_KEYMAP_HAS_SENSORS
|
#if ZMK_KEYMAP_HAS_SENSORS
|
||||||
subscribed = subscribed && slot->sensor_subscribe_params.value_handle;
|
subscribed = subscribed && slot->sensor_subscribe_params.value_handle;
|
||||||
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
|
||||||
subscribed = subscribed && slot->update_hid_indicators;
|
|
||||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING)
|
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING)
|
||||||
subscribed = subscribed && slot->batt_lvl_subscribe_params.value_handle;
|
subscribed = subscribed && slot->batt_lvl_subscribe_params.value_handle;
|
||||||
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) */
|
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) */
|
||||||
|
@ -712,6 +722,8 @@ static void split_central_connected(struct bt_conn *conn, uint8_t conn_err) {
|
||||||
|
|
||||||
confirm_peripheral_slot_conn(conn);
|
confirm_peripheral_slot_conn(conn);
|
||||||
split_central_process_connection(conn);
|
split_central_process_connection(conn);
|
||||||
|
raise_zmk_split_peripheral_status_changed(
|
||||||
|
(struct zmk_split_peripheral_status_changed){.connected = true});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void split_central_disconnected(struct bt_conn *conn, uint8_t reason) {
|
static void split_central_disconnected(struct bt_conn *conn, uint8_t reason) {
|
||||||
|
@ -728,6 +740,8 @@ static void split_central_disconnected(struct bt_conn *conn, uint8_t reason) {
|
||||||
k_msgq_put(&peripheral_batt_lvl_msgq, &ev, K_NO_WAIT);
|
k_msgq_put(&peripheral_batt_lvl_msgq, &ev, K_NO_WAIT);
|
||||||
k_work_submit(&peripheral_batt_lvl_work);
|
k_work_submit(&peripheral_batt_lvl_work);
|
||||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING)
|
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING)
|
||||||
|
raise_zmk_split_peripheral_status_changed(
|
||||||
|
(struct zmk_split_peripheral_status_changed){.connected = false});
|
||||||
|
|
||||||
err = release_peripheral_slot_for_conn(conn);
|
err = release_peripheral_slot_for_conn(conn);
|
||||||
|
|
||||||
|
@ -828,47 +842,85 @@ int zmk_split_bt_invoke_behavior(uint8_t source, struct zmk_behavior_binding *bi
|
||||||
return split_bt_invoke_behavior_payload(wrapper);
|
return split_bt_invoke_behavior_payload(wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
K_THREAD_STACK_DEFINE(split_central_data_xfer_q_stack,
|
||||||
|
CONFIG_ZMK_SPLIT_BLE_CENTRAL_DATA_XFER_STACK_SIZE);
|
||||||
|
|
||||||
static zmk_hid_indicators_t hid_indicators = 0;
|
struct k_work_q split_central_data_xfer_q;
|
||||||
|
|
||||||
static void split_central_update_indicators_callback(struct k_work *work) {
|
K_MSGQ_DEFINE(zmk_split_central_data_xfer_msgq, sizeof(struct zmk_split_data_xfer_data),
|
||||||
zmk_hid_indicators_t indicators = hid_indicators;
|
CONFIG_ZMK_SPLIT_BLE_CENTRAL_DATA_XFER_QUEUE_SIZE, 2);
|
||||||
for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) {
|
|
||||||
|
void split_central_data_xfer_callback(struct k_work *work) {
|
||||||
|
struct zmk_split_data_xfer_data payload;
|
||||||
|
|
||||||
|
while (k_msgq_get(&zmk_split_central_data_xfer_msgq, &payload, K_NO_WAIT) == 0) {
|
||||||
|
for (uint8_t i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) {
|
||||||
if (peripherals[i].state != PERIPHERAL_SLOT_STATE_CONNECTED) {
|
if (peripherals[i].state != PERIPHERAL_SLOT_STATE_CONNECTED) {
|
||||||
|
LOG_ERR("Source not connected");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peripherals[i].update_hid_indicators == 0) {
|
if (!peripherals[i].data_xfer_handle) {
|
||||||
// It appears that sometimes the peripheral is considered connected
|
LOG_ERR("Handle not discovered");
|
||||||
// before the GATT characteristics have been discovered. If this is
|
|
||||||
// the case, the update_hid_indicators handle will not yet be set.
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int err = bt_gatt_write_without_response(peripherals[i].conn,
|
int err = bt_gatt_write_without_response(peripherals[i].conn,
|
||||||
peripherals[i].update_hid_indicators, &indicators,
|
peripherals[i].data_xfer_handle, &payload,
|
||||||
sizeof(indicators), true);
|
sizeof(struct zmk_split_data_xfer_data), true);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_ERR("Failed to write HID indicator characteristic (err %d)", err);
|
LOG_ERR("Failed to write the data transfer characteristic (err %d)", err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static K_WORK_DEFINE(split_central_update_indicators, split_central_update_indicators_callback);
|
K_WORK_DEFINE(split_central_data_xfer_work, split_central_data_xfer_callback);
|
||||||
|
|
||||||
int zmk_split_bt_update_hid_indicator(zmk_hid_indicators_t indicators) {
|
static int split_bt_data_xfer_payload(struct zmk_split_data_xfer_data payload) {
|
||||||
hid_indicators = indicators;
|
LOG_DBG("");
|
||||||
return k_work_submit_to_queue(&split_central_split_run_q, &split_central_update_indicators);
|
|
||||||
|
int err = k_msgq_put(&zmk_split_central_data_xfer_msgq, &payload, K_MSEC(100));
|
||||||
|
if (err) {
|
||||||
|
switch (err) {
|
||||||
|
case -EAGAIN: {
|
||||||
|
LOG_WRN("Consumer message queue full, popping first message and queueing again");
|
||||||
|
struct zmk_split_data_xfer_data discarded_report;
|
||||||
|
k_msgq_get(&zmk_split_central_data_xfer_msgq, &discarded_report, K_NO_WAIT);
|
||||||
|
return split_bt_data_xfer_payload(payload);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
LOG_WRN("Failed to queue data to send (%d)", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
k_work_submit_to_queue(&split_central_data_xfer_q, &split_central_data_xfer_work);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
int zmk_split_central_send_data(enum data_tag tag, uint8_t size, uint8_t *data) {
|
||||||
|
if (size > ZMK_SPLIT_DATA_XFER_MAX_LEN) {
|
||||||
|
LOG_ERR("Payload too large. Size: %d", size);
|
||||||
|
return -EFBIG;
|
||||||
|
}
|
||||||
|
struct zmk_split_data_xfer_data payload;
|
||||||
|
payload.data_tag = tag;
|
||||||
|
payload.data_size = size;
|
||||||
|
memcpy(payload.data, data, size);
|
||||||
|
LOG_HEXDUMP_DBG(&payload, sizeof(struct zmk_split_data_xfer_data), "sending :");
|
||||||
|
return split_bt_data_xfer_payload(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
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_work_queue_start(&split_central_split_run_q, split_central_split_run_q_stack,
|
||||||
K_THREAD_STACK_SIZEOF(split_central_split_run_q_stack),
|
K_THREAD_STACK_SIZEOF(split_central_split_run_q_stack),
|
||||||
CONFIG_ZMK_BLE_THREAD_PRIORITY, NULL);
|
CONFIG_ZMK_BLE_THREAD_PRIORITY, NULL);
|
||||||
|
k_work_queue_start(&split_central_data_xfer_q, split_central_data_xfer_q_stack,
|
||||||
|
K_THREAD_STACK_SIZEOF(split_central_data_xfer_q_stack),
|
||||||
|
CONFIG_ZMK_BLE_THREAD_PRIORITY, NULL);
|
||||||
bt_conn_cb_register(&conn_callbacks);
|
bt_conn_cb_register(&conn_callbacks);
|
||||||
|
|
||||||
return IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START) ? 0 : start_scanning();
|
return IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START) ? 0 : start_scanning();
|
||||||
|
|
|
@ -22,12 +22,9 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
#include <zmk/split/bluetooth/uuid.h>
|
#include <zmk/split/bluetooth/uuid.h>
|
||||||
#include <zmk/split/bluetooth/service.h>
|
#include <zmk/split/bluetooth/service.h>
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
|
||||||
#include <zmk/events/hid_indicators_changed.h>
|
|
||||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
|
||||||
|
|
||||||
#include <zmk/events/sensor_event.h>
|
#include <zmk/events/sensor_event.h>
|
||||||
#include <zmk/sensors.h>
|
#include <zmk/sensors.h>
|
||||||
|
#include <zmk/events/split_data_xfer_event.h>
|
||||||
|
|
||||||
#if ZMK_KEYMAP_HAS_SENSORS
|
#if ZMK_KEYMAP_HAS_SENSORS
|
||||||
static struct sensor_event last_sensor_event;
|
static struct sensor_event last_sensor_event;
|
||||||
|
@ -49,6 +46,7 @@ static uint8_t num_of_positions = ZMK_KEYMAP_LEN;
|
||||||
static uint8_t position_state[POS_STATE_LEN];
|
static uint8_t position_state[POS_STATE_LEN];
|
||||||
|
|
||||||
static struct zmk_split_run_behavior_payload behavior_run_payload;
|
static struct zmk_split_run_behavior_payload behavior_run_payload;
|
||||||
|
static struct zmk_split_data_xfer_data data_xfer_payload;
|
||||||
|
|
||||||
static ssize_t split_svc_pos_state(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
|
static ssize_t split_svc_pos_state(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
|
||||||
void *buf, uint16_t len, uint16_t offset) {
|
void *buf, uint16_t len, uint16_t offset) {
|
||||||
|
@ -101,6 +99,32 @@ static ssize_t split_svc_run_behavior(struct bt_conn *conn, const struct bt_gatt
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void split_svc_data_xfer_callback(struct k_work *work) {
|
||||||
|
LOG_DBG("Size correct, raising event");
|
||||||
|
struct zmk_split_data_xfer_event event;
|
||||||
|
memcpy(&event.data_xfer, &data_xfer_payload, sizeof(struct zmk_split_data_xfer_data));
|
||||||
|
raise_zmk_split_data_xfer_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static K_WORK_DEFINE(split_svc_data_xfer_work, split_svc_data_xfer_callback);
|
||||||
|
|
||||||
|
static ssize_t split_svc_data_xfer(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
|
||||||
|
const void *buf, uint16_t len, uint16_t offset, uint8_t flags) {
|
||||||
|
uint16_t end_addr = offset + len;
|
||||||
|
|
||||||
|
LOG_DBG("offset %d len %d", offset, len);
|
||||||
|
LOG_HEXDUMP_DBG(buf, len, "Receiving :");
|
||||||
|
|
||||||
|
// If whole packet transferred correctly
|
||||||
|
if ((end_addr == sizeof(struct zmk_split_data_xfer_data))) {
|
||||||
|
// Raise new data transfer event with received data
|
||||||
|
memcpy(&data_xfer_payload + offset, buf, len);
|
||||||
|
k_work_submit(&split_svc_data_xfer_work);
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t split_svc_num_of_positions(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
|
static ssize_t split_svc_num_of_positions(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
|
||||||
void *buf, uint16_t len, uint16_t offset) {
|
void *buf, uint16_t len, uint16_t offset) {
|
||||||
return bt_gatt_attr_read(conn, attrs, buf, len, offset, attrs->user_data, sizeof(uint8_t));
|
return bt_gatt_attr_read(conn, attrs, buf, len, offset, attrs->user_data, sizeof(uint8_t));
|
||||||
|
@ -110,34 +134,6 @@ static void split_svc_pos_state_ccc(const struct bt_gatt_attr *attr, uint16_t va
|
||||||
LOG_DBG("value %d", value);
|
LOG_DBG("value %d", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
|
||||||
|
|
||||||
static zmk_hid_indicators_t hid_indicators = 0;
|
|
||||||
|
|
||||||
static void split_svc_update_indicators_callback(struct k_work *work) {
|
|
||||||
LOG_DBG("Raising HID indicators changed event: %x", hid_indicators);
|
|
||||||
raise_zmk_hid_indicators_changed(
|
|
||||||
(struct zmk_hid_indicators_changed){.indicators = hid_indicators});
|
|
||||||
}
|
|
||||||
|
|
||||||
static K_WORK_DEFINE(split_svc_update_indicators_work, split_svc_update_indicators_callback);
|
|
||||||
|
|
||||||
static ssize_t split_svc_update_indicators(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
|
||||||
const void *buf, uint16_t len, uint16_t offset,
|
|
||||||
uint8_t flags) {
|
|
||||||
if (offset + len > sizeof(zmk_hid_indicators_t)) {
|
|
||||||
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy((uint8_t *)&hid_indicators + offset, buf, len);
|
|
||||||
|
|
||||||
k_work_submit(&split_svc_update_indicators_work);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
|
||||||
|
|
||||||
BT_GATT_SERVICE_DEFINE(
|
BT_GATT_SERVICE_DEFINE(
|
||||||
split_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID)),
|
split_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID)),
|
||||||
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID),
|
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID),
|
||||||
|
@ -147,6 +143,9 @@ BT_GATT_SERVICE_DEFINE(
|
||||||
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID),
|
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID),
|
||||||
BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL,
|
BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL,
|
||||||
split_svc_run_behavior, &behavior_run_payload),
|
split_svc_run_behavior, &behavior_run_payload),
|
||||||
|
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_DATA_XFER_UUID),
|
||||||
|
BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL,
|
||||||
|
split_svc_data_xfer, NULL),
|
||||||
BT_GATT_DESCRIPTOR(BT_UUID_NUM_OF_DIGITALS, BT_GATT_PERM_READ, split_svc_num_of_positions, NULL,
|
BT_GATT_DESCRIPTOR(BT_UUID_NUM_OF_DIGITALS, BT_GATT_PERM_READ, split_svc_num_of_positions, NULL,
|
||||||
&num_of_positions),
|
&num_of_positions),
|
||||||
#if ZMK_KEYMAP_HAS_SENSORS
|
#if ZMK_KEYMAP_HAS_SENSORS
|
||||||
|
@ -155,11 +154,6 @@ BT_GATT_SERVICE_DEFINE(
|
||||||
split_svc_sensor_state, NULL, &last_sensor_event),
|
split_svc_sensor_state, NULL, &last_sensor_event),
|
||||||
BT_GATT_CCC(split_svc_sensor_state_ccc, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
|
BT_GATT_CCC(split_svc_sensor_state_ccc, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
|
||||||
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
||||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
|
||||||
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_UPDATE_HID_INDICATORS_UUID),
|
|
||||||
BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL,
|
|
||||||
split_svc_update_indicators, NULL),
|
|
||||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
K_THREAD_STACK_DEFINE(service_q_stack, CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE);
|
K_THREAD_STACK_DEFINE(service_q_stack, CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE);
|
||||||
|
|
Loading…
Add table
Reference in a new issue