Skip to content

Commit

Permalink
feat(ble): Add the ability to enable and disable advertising
Browse files Browse the repository at this point in the history
Added functionality to enable and disable BLE advertising using new &bt behavior bindings, adds documentation for the new parameters and a note that default behavior is unchanged

Co-Authored-By: Nicolas Munnich <[email protected]>
Co-Authored-By: Cem Aksoylar <[email protected]>
  • Loading branch information
3 people committed Nov 21, 2024
1 parent 6934e36 commit cf1c71a
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 7 deletions.
6 changes: 6 additions & 0 deletions app/include/dt-bindings/zmk/bt.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
#define BT_SEL_CMD 3
#define BT_CLR_ALL_CMD 4
#define BT_DISC_CMD 5
#define BT_ADV_OFF_CMD 6
#define BT_ADV_ON_CMD 7
#define BT_ADV_TOG_CMD 8

/*
Note: Some future commands will include additional parameters, so we
Expand All @@ -22,3 +25,6 @@ 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_ADV_OFF BT_ADV_OFF_CMD 0
#define BT_ADV_ON BT_ADV_ON_CMD 0
#define BT_ADV_TOG BT_ADV_TOG_CMD 0
9 changes: 9 additions & 0 deletions app/include/zmk/ble.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
#define ZMK_BLE_PROFILE_COUNT CONFIG_BT_MAX_PAIRED
#endif

enum advertising_type {
ZMK_ADV_NONE,
ZMK_ADV_DIR,
ZMK_ADV_CONN,
};

void zmk_ble_clear_bonds(void);
int zmk_ble_prof_next(void);
int zmk_ble_prof_prev(void);
Expand All @@ -41,6 +47,9 @@ int zmk_ble_unpair_all(void);

int zmk_ble_set_device_name(char *name);

void zmk_ble_adv_enabled_set(bool adv_enabled);
bool zmk_ble_adv_enabled_get(void);

#if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
int zmk_ble_put_peripheral_addr(const bt_addr_le_t *addr);
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) */
24 changes: 24 additions & 0 deletions app/src/behaviors/behavior_bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@ static const struct behavior_parameter_value_metadata no_arg_values[] = {
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BT_CLR_CMD,
},
{
.display_name = "Disconnect All and Stop Advertising",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BT_ADV_OFF_CMD,
},
{
.display_name = "Start Advertising",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BT_ADV_ON_CMD,
},
{
.display_name = "Toggle Advertising",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BT_ADV_TOG_CMD,
},
};

static const struct behavior_parameter_metadata_set no_args_set = {
Expand Down Expand Up @@ -105,6 +120,15 @@ 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_ADV_ON_CMD:
zmk_ble_adv_enabled_set(true);
return 0;
case BT_ADV_OFF_CMD:
zmk_ble_adv_enabled_set(false);
return 0;
case BT_ADV_TOG_CMD:
zmk_ble_adv_enabled_set(zmk_ble_adv_enabled_get() ? false : true);
return 0;
default:
LOG_ERR("Unknown BT command: %d", binding->param1);
}
Expand Down
34 changes: 27 additions & 7 deletions app/src/ble.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,7 @@ RING_BUF_DECLARE(passkey_entries, PASSKEY_DIGITS);

#endif /* IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) */

enum advertising_type {
ZMK_ADV_NONE,
ZMK_ADV_DIR,
ZMK_ADV_CONN,
} advertising_status;
enum advertising_type advertising_status;

#define CURR_ADV(adv) (adv << 4)

Expand All @@ -63,6 +59,8 @@ enum advertising_type {
static struct zmk_ble_profile profiles[ZMK_BLE_PROFILE_COUNT];
static uint8_t active_profile;

static bool permit_adv = true;

#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)

Expand Down Expand Up @@ -167,9 +165,9 @@ int update_advertising(void) {
struct bt_conn *conn;
enum advertising_type desired_adv = ZMK_ADV_NONE;

if (zmk_ble_active_profile_is_open()) {
if (permit_adv && zmk_ble_active_profile_is_open()) {
desired_adv = ZMK_ADV_CONN;
} else if (!zmk_ble_active_profile_is_connected()) {
} else if (permit_adv && !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
Expand Down Expand Up @@ -210,6 +208,28 @@ static void update_advertising_callback(struct k_work *work) { update_advertisin

K_WORK_DEFINE(update_advertising_work, update_advertising_callback);

void zmk_ble_adv_enabled_set(bool adv_enabled) {
if (adv_enabled) {
if (advertising_status != ZMK_ADV_CONN) {
permit_adv = true;
LOG_DBG("Enabling adv");
}
update_advertising();
} else {
permit_adv = false;
LOG_DBG("Disabling adv and disconnecting");
for (int i = 0; i < ZMK_BLE_PROFILE_COUNT; i++) {
int err = zmk_ble_prof_disconnect(i);
if (err) {
LOG_DBG("Failed to disconnect profile %d : %d", i, err);
}
}
update_advertising();
}
}

bool zmk_ble_adv_enabled_get(void) { return permit_adv; }

static void clear_profile_bond(uint8_t profile) {
if (bt_addr_le_cmp(&profiles[profile].peer, BT_ADDR_LE_ANY)) {
bt_unpair(BT_ID_DEFAULT, &profiles[profile].peer);
Expand Down
7 changes: 7 additions & 0 deletions docs/docs/keymaps/behaviors/bluetooth.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,19 @@ Here is a table describing the command for each define:
| `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_ADV_OFF` | Disable advertising and disconnect from all profiles |
| `BT_ADV_ON` | Enable advertising and attempt to reconnect to profiles |
| `BT_ADV_TOG` | Toggle advertising on and off |

:::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.
:::

:::note[Advertising]
Bluetooth advertising is enabled in all situations by default, and doesn't have to be explicitly enabled via the bindings above.
:::

## Bluetooth Behavior

The bluetooth behavior completes an bluetooth action given on press.
Expand Down

0 comments on commit cf1c71a

Please sign in to comment.