feat(split): Use directed advertising.

* Split centrals to scan with their identity so they receive direct
  advertising packets.
* Split peripherals to use direct advertising if they have an existing
  bond to a split central.
This commit is contained in:
Peter Johanson 2023-09-02 01:45:12 -07:00 committed by Pete Johanson
parent 3936298260
commit 718500543b
3 changed files with 45 additions and 4 deletions
app/src/split/bluetooth

View file

@ -14,6 +14,7 @@ config ZMK_SPLIT_ROLE_CENTRAL
select BT_CENTRAL
select BT_GATT_CLIENT
select BT_GATT_AUTO_DISCOVER_CCC
select BT_SCAN_WITH_IDENTITY
if ZMK_SPLIT_ROLE_CENTRAL

View file

@ -511,8 +511,10 @@ static void split_central_device_found(const bt_addr_le_t *addr, int8_t rssi, ui
LOG_DBG("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i", dev, type, ad->len, rssi);
/* We're only interested in connectable events */
if (type == BT_GAP_ADV_TYPE_ADV_IND || type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
if (type == BT_GAP_ADV_TYPE_ADV_IND) {
bt_data_parse(ad, split_central_eir_parse, (void *)addr);
} else if (type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
split_central_eir_found(addr);
}
}

View file

@ -43,15 +43,49 @@ static const struct bt_data zmk_ble_ad[] = {
static bool is_connected = false;
static int start_advertising() {
return bt_le_adv_start(BT_LE_ADV_CONN, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0);
static void each_bond(const struct bt_bond_info *info, void *user_data) {
bt_addr_le_t *addr = (bt_addr_le_t *)user_data;
if (bt_addr_le_cmp(&info->addr, BT_ADDR_LE_NONE) != 0) {
bt_addr_le_copy(addr, &info->addr);
}
}
static int start_advertising(bool low_duty) {
bt_addr_le_t central_addr = bt_addr_le_none;
bt_foreach_bond(BT_ID_DEFAULT, each_bond, &central_addr);
if (bt_addr_le_cmp(&central_addr, BT_ADDR_LE_NONE) != 0) {
struct bt_le_adv_param adv_param = low_duty ? *BT_LE_ADV_CONN_DIR_LOW_DUTY(&central_addr)
: *BT_LE_ADV_CONN_DIR(&central_addr);
return bt_le_adv_start(&adv_param, NULL, 0, NULL, 0);
} else {
return bt_le_adv_start(BT_LE_ADV_CONN, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0);
}
};
static bool low_duty_advertising = false;
static void advertising_cb(struct k_work *work) {
const int err = start_advertising(low_duty_advertising);
if (err < 0) {
LOG_ERR("Failed to start advertising (%d)", err);
}
}
K_WORK_DEFINE(advertising_work, advertising_cb);
static void connected(struct bt_conn *conn, uint8_t err) {
is_connected = (err == 0);
ZMK_EVENT_RAISE(new_zmk_split_peripheral_status_changed(
(struct zmk_split_peripheral_status_changed){.connected = is_connected}));
if (err == BT_HCI_ERR_ADV_TIMEOUT) {
low_duty_advertising = true;
k_work_submit(&advertising_work);
}
}
static void disconnected(struct bt_conn *conn, uint8_t reason) {
@ -65,6 +99,9 @@ static void disconnected(struct bt_conn *conn, uint8_t reason) {
ZMK_EVENT_RAISE(new_zmk_split_peripheral_status_changed(
(struct zmk_split_peripheral_status_changed){.connected = is_connected}));
low_duty_advertising = false;
k_work_submit(&advertising_work);
}
static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) {
@ -119,7 +156,8 @@ static int zmk_peripheral_ble_init(const struct device *_arg) {
#else
bt_conn_cb_register(&conn_callbacks);
start_advertising();
low_duty_advertising = false;
k_work_submit(&advertising_work);
#endif
return 0;