mirror of https://github.com/zmkfirmware/zmk.git
feat(split): Send layer state to peripherals
This commit is contained in:
parent
24487bd974
commit
9813105d1d
|
|
@ -97,6 +97,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_SPLIT app PRIVATE src/events/split_peripheral_status_changed.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_SPLIT app PRIVATE src/events/split_peripheral_layer_changed.c)
|
||||
add_subdirectory_ifdef(CONFIG_ZMK_SPLIT src/split)
|
||||
|
||||
target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/usb.c)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zmk/event_manager.h>
|
||||
|
||||
struct zmk_split_peripheral_layer_changed {
|
||||
uint32_t layers;
|
||||
};
|
||||
|
||||
ZMK_EVENT_DECLARE(zmk_split_peripheral_layer_changed);
|
||||
|
|
@ -20,3 +20,4 @@
|
|||
#define ZMK_SPLIT_BT_UPDATE_HID_INDICATORS_UUID ZMK_BT_SPLIT_UUID(0x00000004)
|
||||
#define ZMK_SPLIT_BT_SELECT_PHYS_LAYOUT_UUID ZMK_BT_SPLIT_UUID(0x00000005)
|
||||
#define ZMK_SPLIT_BT_INPUT_EVENT_UUID ZMK_BT_SPLIT_UUID(0x00000006)
|
||||
#define ZMK_SPLIT_BT_UPDATE_LAYERS_UUID ZMK_BT_SPLIT_UUID(0x00000007)
|
||||
|
|
|
|||
|
|
@ -46,3 +46,5 @@ int zmk_split_central_update_hid_indicator(zmk_hid_indicators_t indicators);
|
|||
int zmk_split_central_get_peripheral_battery_level(uint8_t source, uint8_t *level);
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING)
|
||||
|
||||
int zmk_split_central_update_layers(uint32_t layers);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
void set_peripheral_layers_state(uint32_t new_layers);
|
||||
bool peripheral_layer_active(uint8_t layer);
|
||||
uint8_t peripheral_highest_layer_active(void);
|
||||
|
|
@ -66,6 +66,7 @@ enum zmk_split_transport_central_command_type {
|
|||
ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_INVOKE_BEHAVIOR,
|
||||
ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_SET_PHYSICAL_LAYOUT,
|
||||
ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_SET_HID_INDICATORS,
|
||||
ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_SET_RGB_LAYERS,
|
||||
} __packed;
|
||||
|
||||
struct zmk_split_transport_central_command {
|
||||
|
|
@ -87,5 +88,9 @@ struct zmk_split_transport_central_command {
|
|||
struct {
|
||||
zmk_hid_indicators_t indicators;
|
||||
} set_hid_indicators;
|
||||
|
||||
struct {
|
||||
uint32_t layers;
|
||||
} set_rgb_layers;
|
||||
} data;
|
||||
} __packed;
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zmk/events/split_peripheral_layer_changed.h>
|
||||
|
||||
ZMK_EVENT_IMPL(zmk_split_peripheral_layer_changed);
|
||||
|
|
@ -14,5 +14,6 @@ if (CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
|||
zephyr_linker_sources(SECTIONS ../../include/linker/zmk-split-transport-central.ld)
|
||||
else()
|
||||
target_sources(app PRIVATE peripheral.c)
|
||||
target_sources(app PRIVATE peripheral_layers.c)
|
||||
zephyr_linker_sources(SECTIONS ../../include/linker/zmk-split-transport-peripheral.ld)
|
||||
endif()
|
||||
|
|
@ -33,6 +33,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
#include <zmk/pointing/input_split.h>
|
||||
#include <zmk/hid_indicators_types.h>
|
||||
#include <zmk/physical_layouts.h>
|
||||
#include <zmk/events/split_peripheral_layer_changed.h>
|
||||
|
||||
static int start_scanning(void);
|
||||
|
||||
|
|
@ -60,6 +61,8 @@ struct peripheral_slot {
|
|||
uint16_t update_hid_indicators;
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
uint16_t selected_physical_layout_handle;
|
||||
uint16_t update_layers_handle;
|
||||
|
||||
uint8_t position_state[POSITION_STATE_DATA_LEN];
|
||||
uint8_t changed_positions[POSITION_STATE_DATA_LEN];
|
||||
};
|
||||
|
|
@ -219,6 +222,7 @@ int release_peripheral_slot(int index) {
|
|||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
slot->update_hid_indicators = 0;
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
slot->update_layers_handle = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -620,6 +624,10 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn,
|
|||
LOG_DBG("Found update HID indicators handle");
|
||||
slot->update_hid_indicators = bt_gatt_attr_value_handle(attr);
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
} else if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid,
|
||||
BT_UUID_DECLARE_128(ZMK_SPLIT_BT_UPDATE_LAYERS_UUID))) {
|
||||
LOG_DBG("Found update Layers handle");
|
||||
slot->update_layers_handle = bt_gatt_attr_value_handle(attr);
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING)
|
||||
} else if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid,
|
||||
BT_UUID_BAS_BATTERY_LEVEL)) {
|
||||
|
|
@ -707,6 +715,8 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn,
|
|||
}
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_INPUT_SPLIT)
|
||||
|
||||
subscribed = subscribed && slot->update_layers_handle;
|
||||
|
||||
return subscribed ? BT_GATT_ITER_STOP : BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
|
|
@ -1024,6 +1034,7 @@ K_MSGQ_DEFINE(zmk_split_central_split_run_msgq, sizeof(struct central_cmd_wrappe
|
|||
|
||||
void split_central_split_run_callback(struct k_work *work) {
|
||||
struct central_cmd_wrapper payload_wrapper;
|
||||
int err;
|
||||
|
||||
LOG_DBG("");
|
||||
|
||||
|
|
@ -1056,7 +1067,7 @@ void split_central_split_run_callback(struct k_work *work) {
|
|||
payload.behavior_dev);
|
||||
}
|
||||
|
||||
int err = bt_gatt_write_without_response(
|
||||
err = bt_gatt_write_without_response(
|
||||
peripherals[payload_wrapper.source].conn,
|
||||
peripherals[payload_wrapper.source].run_behavior_handle, &payload,
|
||||
sizeof(struct zmk_split_run_behavior_payload), true);
|
||||
|
|
@ -1082,7 +1093,7 @@ void split_central_split_run_callback(struct k_work *work) {
|
|||
break;
|
||||
}
|
||||
|
||||
int err = bt_gatt_write_without_response(
|
||||
err = bt_gatt_write_without_response(
|
||||
peripherals[payload_wrapper.source].conn,
|
||||
peripherals[payload_wrapper.source].update_hid_indicators,
|
||||
&payload_wrapper.cmd.data.set_hid_indicators.indicators,
|
||||
|
|
@ -1093,6 +1104,18 @@ void split_central_split_run_callback(struct k_work *work) {
|
|||
}
|
||||
break;
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
case ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_SET_RGB_LAYERS:
|
||||
err = bt_gatt_write_without_response(
|
||||
peripherals[payload_wrapper.source].conn,
|
||||
peripherals[payload_wrapper.source].update_layers_handle,
|
||||
&payload_wrapper.cmd.data.set_rgb_layers.layers,
|
||||
sizeof(payload_wrapper.cmd.data.set_rgb_layers.layers), true);
|
||||
|
||||
if (err) {
|
||||
LOG_ERR("Failed to send layers to peripheral (err %d)", err);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_WRN("Unsupported wrapped central command type %d", payload_wrapper.cmd.type);
|
||||
return;
|
||||
|
|
@ -1174,6 +1197,7 @@ static int split_central_bt_send_command(uint8_t source,
|
|||
}
|
||||
|
||||
switch (cmd.type) {
|
||||
case ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_SET_RGB_LAYERS:
|
||||
case ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_SET_HID_INDICATORS:
|
||||
case ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_SET_PHYSICAL_LAYOUT:
|
||||
case ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_INVOKE_BEHAVIOR: {
|
||||
|
|
|
|||
|
|
@ -31,9 +31,11 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
#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/split/peripheral_layers.h>
|
||||
|
||||
#include <zmk/events/sensor_event.h>
|
||||
#include <zmk/sensors.h>
|
||||
#include <zmk/events/split_peripheral_layer_changed.h>
|
||||
|
||||
#if ZMK_KEYMAP_HAS_SENSORS
|
||||
static struct sensor_event last_sensor_event;
|
||||
|
|
@ -139,6 +141,31 @@ static ssize_t split_svc_get_selected_phys_layout(struct bt_conn *conn,
|
|||
return bt_gatt_attr_read(conn, attrs, buf, len, offset, &selected, sizeof(selected));
|
||||
}
|
||||
|
||||
static uint32_t layers = 0;
|
||||
|
||||
static void split_svc_update_layers_callback(struct k_work *work) {
|
||||
LOG_DBG("Setting peripheral layers: %x", layers);
|
||||
// set_peripheral_layers_state(layers);
|
||||
raise_zmk_split_peripheral_layer_changed(
|
||||
(struct zmk_split_peripheral_layer_changed){.layers = layers});
|
||||
}
|
||||
|
||||
static K_WORK_DEFINE(split_svc_update_layers_work, split_svc_update_layers_callback);
|
||||
|
||||
static ssize_t split_svc_update_layers(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(uint32_t)) {
|
||||
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
|
||||
}
|
||||
|
||||
memcpy((uint8_t *)&layers + offset, buf, len);
|
||||
|
||||
k_work_submit(&split_svc_update_layers_work);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_INPUT_SPLIT)
|
||||
|
||||
static void split_input_events_ccc(const struct bt_gatt_attr *attr, uint16_t value) {
|
||||
|
|
@ -204,8 +231,11 @@ BT_GATT_SERVICE_DEFINE(
|
|||
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SELECT_PHYS_LAYOUT_UUID),
|
||||
BT_GATT_CHRC_WRITE | BT_GATT_CHRC_READ,
|
||||
BT_GATT_PERM_WRITE_ENCRYPT | BT_GATT_PERM_READ_ENCRYPT,
|
||||
split_svc_get_selected_phys_layout, split_svc_select_phys_layout,
|
||||
NULL), );
|
||||
split_svc_get_selected_phys_layout, split_svc_select_phys_layout, NULL),
|
||||
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_UPDATE_LAYERS_UUID),
|
||||
BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL,
|
||||
split_svc_update_layers, NULL), );
|
||||
|
||||
K_THREAD_STACK_DEFINE(service_q_stack, CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE);
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,42 @@ int zmk_split_central_update_hid_indicator(zmk_hid_indicators_t indicators) {
|
|||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
|
||||
int zmk_split_central_update_layers(uint32_t new_layers) {
|
||||
if (!active_transport || !active_transport->api ||
|
||||
!active_transport->api->get_available_source_ids || !active_transport->api->send_command) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
uint8_t source_ids[ZMK_SPLIT_CENTRAL_PERIPHERAL_COUNT];
|
||||
|
||||
int ret = active_transport->api->get_available_source_ids(source_ids);
|
||||
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct zmk_split_transport_central_command command =
|
||||
(struct zmk_split_transport_central_command){
|
||||
.type = ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_SET_RGB_LAYERS,
|
||||
.data =
|
||||
{
|
||||
.set_rgb_layers =
|
||||
{
|
||||
.layers = new_layers,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ret; i++) {
|
||||
ret = active_transport->api->send_command(source_ids[i], command);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING)
|
||||
|
||||
int zmk_split_central_get_peripheral_battery_level(uint8_t source, uint8_t *level) {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
#include <zmk/events/hid_indicators_changed.h>
|
||||
#endif
|
||||
#include <zmk/events/split_peripheral_layer_changed.h>
|
||||
|
||||
#include <zephyr/init.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
|
@ -66,6 +67,10 @@ int zmk_split_transport_peripheral_command_handler(
|
|||
.indicators = cmd.data.set_hid_indicators.indicators});
|
||||
}
|
||||
#endif
|
||||
case ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_SET_RGB_LAYERS: {
|
||||
return raise_zmk_split_peripheral_layer_changed(
|
||||
(struct zmk_split_peripheral_layer_changed){.layers = cmd.data.set_rgb_layers.layers});
|
||||
}
|
||||
default:
|
||||
LOG_WRN("Unhandled command type %d", cmd.type);
|
||||
return -ENOTSUP;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#include <zmk/split/peripheral_layers.h>
|
||||
#include <zmk/keymap.h>
|
||||
|
||||
static uint32_t peripheral_layers = 0;
|
||||
|
||||
void set_peripheral_layers_state(uint32_t new_layers) { peripheral_layers = new_layers; }
|
||||
|
||||
bool peripheral_layer_active(uint8_t layer) {
|
||||
return (peripheral_layers & (BIT(layer))) == (BIT(layer));
|
||||
};
|
||||
|
||||
uint8_t peripheral_highest_layer_active(void) {
|
||||
if (peripheral_layers > 0) {
|
||||
for (uint8_t layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer > 0; layer--) {
|
||||
if ((peripheral_layers & (BIT(layer))) == (BIT(layer)) || layer == 0) {
|
||||
return layer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -185,6 +185,8 @@ static ssize_t get_payload_data_size(const struct zmk_split_transport_central_co
|
|||
return sizeof(cmd->data.set_physical_layout);
|
||||
case ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_SET_HID_INDICATORS:
|
||||
return sizeof(cmd->data.set_hid_indicators);
|
||||
case ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_SET_RGB_LAYERS:
|
||||
return sizeof(cmd->data.set_rgb_layers);
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue