diff --git a/app/Kconfig b/app/Kconfig index a05abcaba3d..75bceaff910 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -168,6 +168,10 @@ config ZMK_BLE_PASSKEY_ENTRY default n select RING_BUFFER +config ZMK_HANDLE_BLE_DISCONNECTION + bool "Experimental: Respect user disconnection request from computer" + default n + config BT_PERIPHERAL_PREF_MIN_INT default 6 diff --git a/app/src/ble.c b/app/src/ble.c index f35abfa98cf..f2b228ce1d6 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -37,6 +37,11 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include +#if IS_ENABLED(CONFIG_ZMK_HANDLE_BLE_DISCONNECTION) +#include +#include +#endif /* IS_ENABLED(CONFIG_ZMK_HANDLE_BLE_DISCONNECTION) */ + #if IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) #include @@ -62,6 +67,10 @@ enum advertising_type { static struct zmk_ble_profile profiles[ZMK_BLE_PROFILE_COUNT]; static uint8_t active_profile; +#if IS_ENABLED(CONFIG_ZMK_HANDLE_BLE_DISCONNECTION) +bool active_profile_seeking_connection = true; +#endif + #define DEVICE_NAME CONFIG_BT_DEVICE_NAME #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) @@ -167,15 +176,23 @@ int update_advertising() { if (zmk_ble_active_profile_is_open()) { desired_adv = ZMK_ADV_CONN; - } else if (!zmk_ble_active_profile_is_connected()) { - desired_adv = ZMK_ADV_CONN; - // Need to fix directed advertising for privacy centrals. See - // https://github.com/zephyrproject-rtos/zephyr/pull/14984 char - // addr_str[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(zmk_ble_active_profile_addr(), addr_str, - // sizeof(addr_str)); - - // LOG_DBG("Directed advertising to %s", addr_str); - // desired_adv = ZMK_ADV_DIR; + } else { +#if IS_ENABLED(CONFIG_ZMK_HANDLE_BLE_DISCONNECTION) + if (!zmk_ble_active_profile_is_connected() && active_profile_seeking_connection) { + desired_adv = ZMK_ADV_CONN; + } +#else + if (!zmk_ble_active_profile_is_connected()) { + desired_adv = ZMK_ADV_CONN; + // Need to fix directed advertising for privacy centrals. See + // https://github.com/zephyrproject-rtos/zephyr/pull/14984 char + // addr_str[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(zmk_ble_active_profile_addr(), + // addr_str, sizeof(addr_str)); + + // LOG_DBG("Directed advertising to %s", addr_str); + // desired_adv = ZMK_ADV_DIR; + } +#endif /* IS_ENABLED(CONFIG_ZMK_HANDLE_BLE_DISCONNECTION) */ } LOG_DBG("advertising from %d to %d", advertising_status, desired_adv); @@ -262,6 +279,9 @@ int zmk_ble_prof_select(uint8_t index) { active_profile = index; ble_save_profile(); +#if IS_ENABLED(CONFIG_ZMK_HANDLE_BLE_DISCONNECTION) + active_profile_seeking_connection = true; +#endif update_advertising(); raise_profile_changed_event(); @@ -431,6 +451,9 @@ static void connected(struct bt_conn *conn, uint8_t err) { update_advertising(); if (is_conn_active_profile(conn)) { +#if IS_ENABLED(CONFIG_ZMK_HANDLE_BLE_DISCONNECTION) + active_profile_seeking_connection = false; +#endif LOG_DBG("Active profile connected"); k_work_submit(&raise_profile_changed_event_work); } @@ -741,4 +764,18 @@ ZMK_LISTENER(zmk_ble, zmk_ble_listener); ZMK_SUBSCRIPTION(zmk_ble, zmk_keycode_state_changed); #endif /* IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) */ -SYS_INIT(zmk_ble_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); \ No newline at end of file +#if IS_ENABLED(CONFIG_ZMK_HANDLE_BLE_DISCONNECTION) +/* Restart BLE advertsing after user key press */ +static int ble_keypress_listener(const zmk_event_t *eh) { + if (as_zmk_keycode_state_changed(eh) != NULL && !active_profile_seeking_connection && + !zmk_ble_active_profile_is_connected()) { + active_profile_seeking_connection = true; + k_work_submit(&update_advertising_work); + } + return 0; +} +ZMK_LISTENER(ble_keypress, ble_keypress_listener); +ZMK_SUBSCRIPTION(ble_keypress, zmk_keycode_state_changed); +#endif /* IS_ENABLED(CONFIG_ZMK_HANDLE_BLE_DISCONNECTION) */ + +SYS_INIT(zmk_ble_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); diff --git a/docs/docs/config/system.md b/docs/docs/config/system.md index 5a5ae5a55a0..b4235a17eea 100644 --- a/docs/docs/config/system.md +++ b/docs/docs/config/system.md @@ -77,6 +77,7 @@ for more information on configuring Bluetooth. | `CONFIG_ZMK_BLE_THREAD_PRIORITY` | int | Priority of the BLE notify thread | 5 | | `CONFIG_ZMK_BLE_THREAD_STACK_SIZE` | int | Stack size of the BLE notify thread | 512 | | `CONFIG_ZMK_BLE_PASSKEY_ENTRY` | bool | Experimental: require typing passkey from host to pair BLE connection | n | +| `CONFIG_ZMK_HANDLE_BLE_DISCONNECTION` | bool | Experimental: respect user BLE disconnection request from computer | n | Note that `CONFIG_BT_MAX_CONN` and `CONFIG_BT_MAX_PAIRED` should be set to the same value. On a split keyboard they should only be set for the central and must be set to one greater than the desired number of bluetooth profiles.