Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ble): Add the ability to enable and disable advertising #2546

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 ADV_OFF BT_ADV_OFF_CMD 0
#define ADV_ON BT_ADV_ON_CMD 0
#define 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_mode_set(bool mode);
enum advertising_type zmk_ble_adv_mode_get();

#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_mode_set(true);
return 0;
case BT_ADV_OFF_CMD:
zmk_ble_adv_mode_set(false);
return 0;
case BT_ADV_TOG_CMD:
zmk_ble_adv_mode_set((zmk_ble_adv_mode_get() == ZMK_ADV_CONN) ? 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_mode_set(bool mode) {
if (mode) {
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();
}
}

enum advertising_type zmk_ble_adv_mode_get() { return advertising_status; }

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
3 changes: 3 additions & 0 deletions docs/docs/keymaps/behaviors/bluetooth.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ 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`. |
| `ADV_OFF` | Disable advertising and disconnect from all profiles |
| `ADV_ON` | Enable advertising and attempt to reconnect to profiles |
| `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.
Expand Down
Loading