diff --git a/app/src/split/bluetooth/CMakeLists.txt b/app/src/split/bluetooth/CMakeLists.txt index f4e12a9d097..5a81515380d 100644 --- a/app/src/split/bluetooth/CMakeLists.txt +++ b/app/src/split/bluetooth/CMakeLists.txt @@ -7,6 +7,7 @@ if (NOT CONFIG_ZMK_SPLIT_ROLE_CENTRAL) endif() if (CONFIG_ZMK_SPLIT_ROLE_CENTRAL) target_sources(app PRIVATE central.c) + target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_PREF_IDLE app PRIVATE central_idle.c) endif() if (CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_PROXY) diff --git a/app/src/split/bluetooth/Kconfig b/app/src/split/bluetooth/Kconfig index 5f4a782f772..930a12fc920 100644 --- a/app/src/split/bluetooth/Kconfig +++ b/app/src/split/bluetooth/Kconfig @@ -74,6 +74,26 @@ config ZMK_SPLIT_BLE_PREF_TIMEOUT int "Supervision timeout to use for split central/peripheral connection" default 400 +config ZMK_SPLIT_BLE_PREF_IDLE + bool "Set slower split peripheral BLE params on idle to save power" + default y + +if ZMK_SPLIT_BLE_PREF_IDLE + +config ZMK_SPLIT_BLE_PREF_IDLE_INT + int "Idle connection interval to use for split central/peripheral connection" + default 18 + +config ZMK_SPLIT_BLE_PREF_IDLE_LATENCY + int "Idle latency to use for split central/peripheral connection" + default 10 + +config ZMK_SPLIT_BLE_PREF_IDLE_TIMEOUT + int "Idle supervision timeout to use for split central/peripheral connection" + default 400 + +endif # ZMK_SPLIT_BLE_PREF_IDLE + endif # ZMK_SPLIT_ROLE_CENTRAL if !ZMK_SPLIT_ROLE_CENTRAL diff --git a/app/src/split/bluetooth/central_idle.c b/app/src/split/bluetooth/central_idle.c new file mode 100644 index 00000000000..536e1b4589f --- /dev/null +++ b/app/src/split/bluetooth/central_idle.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2025 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#include +#include + +#include +#include + +static void set_sleep_params(struct bt_conn *conn, void *data) { + struct bt_conn_info info; + + bt_conn_get_info(conn, &info); + + if (info.role == BT_CONN_ROLE_CENTRAL && info.state == BT_CONN_STATE_CONNECTED) { + int err = + bt_conn_le_param_update(conn, BT_LE_CONN_PARAM(CONFIG_ZMK_SPLIT_BLE_PREF_IDLE_INT, + CONFIG_ZMK_SPLIT_BLE_PREF_IDLE_INT, + CONFIG_ZMK_SPLIT_BLE_PREF_IDLE_LATENCY, + CONFIG_ZMK_SPLIT_BLE_PREF_IDLE_TIMEOUT)); + + if (err) { + LOG_DBG("Failed to set idle params on split connection: %d", err); + } + } +} + +static void set_wake_params(struct bt_conn *conn, void *data) { + struct bt_conn_info info; + + bt_conn_get_info(conn, &info); + + if (info.role == BT_CONN_ROLE_CENTRAL && info.state == BT_CONN_STATE_CONNECTED) { + int err = bt_conn_le_param_update( + conn, + BT_LE_CONN_PARAM(CONFIG_ZMK_SPLIT_BLE_PREF_INT, CONFIG_ZMK_SPLIT_BLE_PREF_INT, + CONFIG_ZMK_SPLIT_BLE_PREF_LATENCY, CONFIG_ZMK_SPLIT_BLE_PREF_TIMEOUT)); + + if (err) { + LOG_DBG("Failed to set active params on split connection: %d", err); + } + } +} + +static void sleep_all(void) { + LOG_DBG("Setting idle connection parameters on peripherals"); + + bt_conn_foreach(BT_CONN_TYPE_LE, set_sleep_params, NULL); +} + +static void wake_all(void) { + LOG_DBG("Waking up from idle connection parameters on peripherals"); + + bt_conn_foreach(BT_CONN_TYPE_LE, set_wake_params, NULL); +} + +static int central_idle_listener(const zmk_event_t *eh) { + struct zmk_activity_state_changed *ev = as_zmk_activity_state_changed(eh); + if (ev == NULL) { + return -ENOTSUP; + } + + switch (ev->state) { + case ZMK_ACTIVITY_ACTIVE: + wake_all(); + break; + case ZMK_ACTIVITY_IDLE: + sleep_all(); + break; + case ZMK_ACTIVITY_SLEEP: + break; + default: + LOG_WRN("Unhandled activity state: %d", ev->state); + return -EINVAL; + } + return 0; +} + +ZMK_LISTENER(central_idle, central_idle_listener); +ZMK_SUBSCRIPTION(central_idle, zmk_activity_state_changed); diff --git a/app/west.yml b/app/west.yml index d177f2bd1c0..6e3cbe06728 100644 --- a/app/west.yml +++ b/app/west.yml @@ -4,10 +4,12 @@ manifest: url-base: https://github.com/zephyrproject-rtos - name: zmkfirmware url-base: https://github.com/zmkfirmware + - name: carrefinho + url-base: https://github.com/carrefinho projects: - name: zephyr - remote: zmkfirmware - revision: v4.1.0+zmk-fixes + remote: carrefinho + revision: v4.1.0+zmk-fixes+split-conn-fix clone-depth: 1 import: name-blocklist: