From 06023f91c92e7ba01e6c0e29d26b336928ff26b0 Mon Sep 17 00:00:00 2001 From: Chengxin Wang Date: Fri, 28 Jul 2023 21:14:49 +0000 Subject: [PATCH] feat(ble): handle BLE disconnection request - added switch `CONFIG_ZMK_HANDLE_BLE_DISCONNECTION` - fix KinesisCorporation/Adv360-Pro-ZMK#172 --- app/Kconfig | 4 +++ app/src/ble.c | 55 +++++++++++++++++++++++++++++++------- docs/docs/config/system.md | 1 + 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/app/Kconfig b/app/Kconfig index bc134fa8379..9661a669ac9 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -162,6 +162,10 @@ config ZMK_BLE_PASSKEY_ENTRY bool "Experimental: Requiring typing passkey from host to pair BLE connection" default n +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 ac0e40a39af..350b72552b8 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -36,6 +36,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 @@ -68,6 +73,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) @@ -173,15 +182,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); @@ -268,6 +285,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(); @@ -406,6 +426,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); } @@ -694,4 +717,18 @@ ZMK_LISTENER(zmk_ble, zmk_ble_listener); ZMK_SUBSCRIPTION(zmk_ble, zmk_keycode_state_changed); #endif /* IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) */ +#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.