feat(ble): Add option to disable profile auto save

Add Kconfig option to disable persisting the BLE profile index after
every change. This is useful if the user wants to have the same profile
connected at startup regardless of which profile was connected last.

Add `&bt BT_SAVE` command to manually persist the currently active BLE
profile, ensuring it is selected as the active profile on startup.
This commit is contained in:
Thomas Huber 2024-06-07 13:41:07 -07:00
parent 308d6bce6e
commit 9dc769496a
No known key found for this signature in database
GPG key ID: C8B2604C5DD56D87
7 changed files with 40 additions and 20 deletions

View file

@ -179,6 +179,13 @@ config ZMK_BLE_PASSKEY_ENTRY
bool "Require passkey entry on the keyboard to complete pairing"
select RING_BUFFER
config ZMK_BLE_PERSIST_PROFILE_ON_CHANGE
bool "Persist the active BLE profile on change"
default y
help
Enables persisting the active BLE profile on change (after ZMK_SETTINGS_SAVE_DEBOUNCE ms),
ensuring it is active on startup.
config BT_SMP_ALLOW_UNAUTH_OVERWRITE
imply ZMK_BLE_PASSKEY_ENTRY

View file

@ -10,6 +10,7 @@
#define BT_SEL_CMD 3
#define BT_CLR_ALL_CMD 4
#define BT_DISC_CMD 5
#define BT_SAVE_CMD 6
/*
Note: Some future commands will include additional parameters, so we
@ -22,3 +23,4 @@ defines these aliases up front.
#define BT_SEL BT_SEL_CMD
#define BT_CLR_ALL BT_CLR_ALL_CMD 0
#define BT_DISC BT_DISC_CMD
#define BT_SAVE BT_SAVE_CMD 0

View file

@ -26,6 +26,7 @@ int zmk_ble_prof_prev(void);
int zmk_ble_prof_select(uint8_t index);
void zmk_ble_clear_all_bonds(void);
int zmk_ble_prof_disconnect(uint8_t index);
void zmk_ble_save_profile(bool immediate);
int zmk_ble_active_profile_index(void);
int zmk_ble_profile_index(const bt_addr_le_t *addr);

View file

@ -37,6 +37,9 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
return 0;
case BT_DISC_CMD:
return zmk_ble_prof_disconnect(binding->param2);
case BT_SAVE_CMD:
zmk_ble_save_profile(true);
return 0;
default:
LOG_ERR("Unknown BT command: %d", binding->param1);
}

View file

@ -251,16 +251,16 @@ int zmk_ble_profile_index(const bt_addr_le_t *addr) {
#if IS_ENABLED(CONFIG_SETTINGS)
static void ble_save_profile_work(struct k_work *work) {
settings_save_one("ble/active_profile", &active_profile, sizeof(active_profile));
LOG_DBG("Saved active profile %d.", active_profile);
}
static struct k_work_delayable ble_save_work;
#endif
static int ble_save_profile(void) {
void zmk_ble_save_profile(bool immediate) {
#if IS_ENABLED(CONFIG_SETTINGS)
return k_work_reschedule(&ble_save_work, K_MSEC(CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE));
#else
return 0;
int delay = immediate ? 0 : CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE;
k_work_reschedule(&ble_save_work, K_MSEC(delay));
#endif
}
@ -275,7 +275,9 @@ int zmk_ble_prof_select(uint8_t index) {
}
active_profile = index;
ble_save_profile();
#if IS_ENABLED(CONFIG_ZMK_BLE_PERSIST_PROFILE_ON_CHANGE)
zmk_ble_save_profile(false);
#endif
update_advertising();
@ -407,6 +409,7 @@ static int ble_profiles_handle_set(const char *name, size_t len, settings_read_c
LOG_ERR("Failed to handle active profile from settings (err %d)", err);
return err;
}
LOG_DBG("Loaded active profile %d", active_profile);
}
#if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
else if (settings_name_steq(name, "peripheral_addresses", &next) && next) {

View file

@ -38,18 +38,21 @@ This will allow you to reference the actions defined in this header such as `BT_
Here is a table describing the command for each define:
| Define | Action |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `BT_CLR` | Clear bond information between the keyboard and host for the selected profile. |
| `BT_CLR_ALL` | Clear bond information between the keyboard and host for all profiles. |
| `BT_NXT` | Switch to the next profile, cycling through to the first one when the end is reached. |
| `BT_PRV` | Switch to the previous profile, cycling through to the last one when the beginning is reached. |
| `BT_SEL` | Select the 0-indexed profile by number; must include a number as an argument in the keymap to work correctly, e.g. `BT_SEL 0`. |
| `BT_DISC` | Disconnect from the 0-indexed profile by number, if it's currently connected and inactive; must include a number as an argument in the keymap to work correctly, e.g. `BT_DISC 0`. |
| Define | Action |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `BT_CLR` | Clear bond information between the keyboard and host for the selected profile. |
| `BT_CLR_ALL` | Clear bond information between the keyboard and host for all profiles. |
| `BT_NXT` | Switch to the next profile, cycling through to the first one when the end is reached. |
| `BT_PRV` | Switch to the previous profile, cycling through to the last one when the beginning is reached. |
| `BT_SEL` | Select the 0-indexed profile by number; must include a number as an argument in the keymap to work correctly, e.g. `BT_SEL 0`. |
| `BT_DISC` | Disconnect from the 0-indexed profile by number, if it's currently connected and inactive; must include a number as an argument in the keymap to work correctly, e.g. `BT_DISC 0`. |
| `BT_SAVE` | Saves the currently selected profile, ensuring it is active at startup. <br/><br/>Note: This is only useful if `ZMK_CONFIG_BLE_PERSIST_PROFILE_ON_CHANGE` is disabled. Per default the active profile will be persisted on change automatically. |
:::note[Selected profile persistence]
The profile that is selected by the `BT_SEL`/`BT_PRV`/`BT_NXT` actions will be saved to flash storage and hence persist across restarts and firmware flashes.
However it will only be saved after [`CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE`](../config/system.md#general) milliseconds in order to reduce potential wear on the flash memory.
[`CONFIG_ZMK_BLE_PERSIST_PROFILE_ON_CHANGE`](../config/bluetooth.md) can be used to disable automatic saving of the selected profile to flash storage. In this case `BT_SAVE` can be used to manually persist the currently selected profile to change the active profile at startup.
:::
## Bluetooth Behavior

View file

@ -9,10 +9,11 @@ See [Configuration Overview](index.md) for instructions on how to change these s
## Kconfig
| Option | Type | Description | Default |
| -------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
| `CONFIG_ZMK_BLE_EXPERIMENTAL_CONN` | bool | Enables a combination of settings that are planned to be default in future versions of ZMK to improve connection stability. This includes changes to timing on BLE pairing initiation, restores use of the updated/new LLCP implementation, and disables 2M PHY support. | n |
| `CONFIG_ZMK_BLE_EXPERIMENTAL_SEC` | bool | Enables a combination of settings that are planned to be officially supported in the future. This includes enabling BT Secure Connection passkey entry, and allows overwrite of keys from previously paired hosts. | n |
| `CONFIG_ZMK_BLE_EXPERIMENTAL_FEATURES` | bool | Aggregate config that enables both `CONFIG_ZMK_BLE_EXPERIMENTAL_CONN` and `CONFIG_ZMK_BLE_EXPERIMENTAL_SEC`. | n |
| `CONFIG_ZMK_BLE_PASSKEY_ENTRY` | bool | Enable passkey entry during pairing for enhanced security. (Note: After enabling this, you will need to re-pair all previously paired hosts.) | n |
| `CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION` | bool | Low level setting for GATT subscriptions. Set to `n` to work around an annoying Windows bug with battery notifications. | y |
| Option | Type | Description | Default |
| ------------------------------------------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
| `CONFIG_ZMK_BLE_EXPERIMENTAL_CONN` | bool | Enables a combination of settings that are planned to be default in future versions of ZMK to improve connection stability. This includes changes to timing on BLE pairing initiation, restores use of the updated/new LLCP implementation, and disables 2M PHY support. | n |
| `CONFIG_ZMK_BLE_EXPERIMENTAL_SEC` | bool | Enables a combination of settings that are planned to be officially supported in the future. This includes enabling BT Secure Connection passkey entry, and allows overwrite of keys from previously paired hosts. | n |
| `CONFIG_ZMK_BLE_EXPERIMENTAL_FEATURES` | bool | Aggregate config that enables both `CONFIG_ZMK_BLE_EXPERIMENTAL_CONN` and `CONFIG_ZMK_BLE_EXPERIMENTAL_SEC`. | n |
| `CONFIG_ZMK_BLE_PASSKEY_ENTRY` | bool | Enable passkey entry during pairing for enhanced security. (Note: After enabling this, you will need to re-pair all previously paired hosts.) | n |
| `CONFIG_ZMK_BLE_PERSIST_PROFILE_ON_CHANGE` | bool | Enables the new profile to be saved upon selection, ensuring it is active at startup. (Note: The profile is only saved after a delay of `CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE` milliseconds, to minimize potential wear on the flash memory.) | y |
| `CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION` | bool | Low level setting for GATT subscriptions. Set to `n` to work around an annoying Windows bug with battery notifications. | y |