Browse Source

fix(bluetooth): Remove identity, minimal `bt`.

* Simplify the `bt` behavior to one current command
  `BT_CLEAR_BONDS_CMD`.
* Simplify BLE code for split and non-split keyboards.
* Remove keymap processing from split peripheral side.
xmkb
Pete Johanson 4 years ago
parent
commit
fc0812bd2e
  1. 4
      app/CMakeLists.txt
  2. 23
      app/Kconfig
  3. 17
      app/include/dt-bindings/zmk/bt.h
  4. 7
      app/include/zmk/ble.h
  5. 16
      app/src/behaviors/behavior_bt.c
  6. 156
      app/src/ble.c
  7. 1
      app/src/split_listener.c
  8. 58
      docs/docs/behavior/bluetooth.md

4
app/CMakeLists.txt

@ -41,9 +41,7 @@ target_sources(app PRIVATE src/behaviors/behavior_toggle_layer.c)
target_sources(app PRIVATE src/behaviors/behavior_transparent.c) target_sources(app PRIVATE src/behaviors/behavior_transparent.c)
target_sources(app PRIVATE src/behaviors/behavior_none.c) target_sources(app PRIVATE src/behaviors/behavior_none.c)
target_sources(app PRIVATE src/behaviors/behavior_sensor_rotate_key_press.c) target_sources(app PRIVATE src/behaviors/behavior_sensor_rotate_key_press.c)
if(NOT CONFIG_ZMK_BLE_SPLIT_PERIPHERAL) target_sources(app PRIVATE src/keymap.c)
target_sources(app PRIVATE src/keymap.c)
endif()
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/behaviors/behavior_rgb_underglow.c) target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/behaviors/behavior_rgb_underglow.c)
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/behaviors/behavior_bt.c) target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/behaviors/behavior_bt.c)
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble.c) target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble.c)

23
app/Kconfig

@ -40,6 +40,8 @@ menuconfig ZMK_BLE
select BT_PERIPHERAL select BT_PERIPHERAL
select BT_GATT_DIS select BT_GATT_DIS
select BT_GATT_BAS select BT_GATT_BAS
select BT_SETTINGS
select SETTINGS
if ZMK_BLE if ZMK_BLE
@ -47,12 +49,6 @@ config ZMK_BLE_INIT_PRIORITY
int "Init Priority" int "Init Priority"
default 50 default 50
config SETTINGS
default y
config BT_SETTINGS
default y
config SYSTEM_WORKQUEUE_STACK_SIZE config SYSTEM_WORKQUEUE_STACK_SIZE
default 2048 default 2048
@ -144,21 +140,6 @@ endif
endmenu endmenu
if ZMK_BLE && !ZMK_SPLIT_BLE
config BT_ID_MAX
default 5
config BT_MAX_PAIRED
default 5
# Used to update the name to include the identity used
config BT_DEVICE_NAME_DYNAMIC
default y
endif
config ZMK_KSCAN_MOCK_DRIVER config ZMK_KSCAN_MOCK_DRIVER
bool "Enable mock kscan driver to simulate key presses" bool "Enable mock kscan driver to simulate key presses"
default n default n

17
app/include/dt-bindings/zmk/bt.h

@ -4,14 +4,11 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
#define BT_RST_CMD 0 #define BT_CLEAR_BONDS_CMD 0
#define BT_IDENT_NEXT_CMD 1
#define BT_IDENT_PREV_CMD 2
#define BT_IDENT_SEL_CMD 3
#define BT_IDENT_CLR_CMD 4
#define BT_RST BT_RST_CMD 0 /*
#define BT_IDENT_NEXT BT_IDENT_NEXT_CMD 0 Note: Some future commands will include additional parameters, so we
#define BT_IDENT_PREV BT_IDENT_PREV_CMD 0 defines these aliases up front.
#define BT_IDENT_SEL BT_IDENT_SEL_CMD */
#define BT_IDENT_CLR BT_IDENT_CLR_CMD 0
#define BT_CLEAR_BONDS BT_CLEAR_BONDS_CMD 0

7
app/include/zmk/ble.h

@ -9,13 +9,8 @@
#include <bluetooth/addr.h> #include <bluetooth/addr.h>
#include <zmk/keys.h> #include <zmk/keys.h>
int zmk_ble_adv_pause();
int zmk_ble_adv_resume();
int zmk_ble_identity_clear(); int zmk_ble_clear_bonds();
int zmk_ble_identity_next();
int zmk_ble_identity_prev();
int zmk_ble_identity_select(u8_t index);
int zmk_ble_unpair_all(); int zmk_ble_unpair_all();
bool zmk_ble_handle_key_user(struct zmk_key_event *key_event); bool zmk_ble_handle_key_user(struct zmk_key_event *key_event);

16
app/src/behaviors/behavior_bt.c

@ -22,18 +22,10 @@ static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t c
{ {
switch (command) switch (command)
{ {
case BT_RST_CMD: case BT_CLEAR_BONDS_CMD:
return zmk_ble_unpair_all(); return zmk_ble_clear_bonds();
case BT_IDENT_CLR_CMD: default:
return zmk_ble_identity_clear(); LOG_ERR("Unknown BT command: %d", command);
#if CONFIG_BT_ID_MAX != 1
case BT_IDENT_NEXT_CMD:
return zmk_ble_identity_next();
case BT_IDENT_PREV_CMD:
return zmk_ble_identity_prev();
case BT_IDENT_SEL_CMD:
return zmk_ble_identity_select(arg);
#endif /* BT_ID_MAX != 1 */
} }
return -ENOTSUP; return -ENOTSUP;

156
app/src/ble.c

@ -82,8 +82,6 @@ static const struct bt_data zmk_ble_ad[] = {
#endif #endif
}; };
#define IDENTITY_COUNT CONFIG_BT_ID_MAX
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) #if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
static bt_addr_le_t peripheral_addr; static bt_addr_le_t peripheral_addr;
@ -91,8 +89,6 @@ static bt_addr_le_t peripheral_addr;
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */ #endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
static u8_t active_identity = 0;
int zmk_ble_adv_pause() int zmk_ble_adv_pause()
{ {
int err = bt_le_adv_stop(); int err = bt_le_adv_stop();
@ -106,7 +102,7 @@ int zmk_ble_adv_pause()
int zmk_ble_adv_resume() int zmk_ble_adv_resume()
{ {
struct bt_le_adv_param *adv_params = ZMK_ADV_PARAMS(active_identity); struct bt_le_adv_param *adv_params = ZMK_ADV_PARAMS(BT_ID_DEFAULT);
LOG_DBG(""); LOG_DBG("");
int err = bt_le_adv_start(adv_params, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0); int err = bt_le_adv_start(adv_params, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0);
@ -131,62 +127,6 @@ static void disconnect_host_connection(struct bt_conn *conn, void *arg)
bt_conn_disconnect(conn, BT_HCI_ERR_LOCALHOST_TERM_CONN); bt_conn_disconnect(conn, BT_HCI_ERR_LOCALHOST_TERM_CONN);
}; };
static int activate_profile(u8_t index)
{
int err;
if (index >= IDENTITY_COUNT) {
return -EINVAL;
}
if (active_identity != index) {
LOG_DBG("Persisting new active identity");
active_identity = index;
#if IS_ENABLED(CONFIG_SETTINGS)
err = settings_save_one("ble/active_identity", &active_identity, sizeof(u8_t));
if (err) {
LOG_WRN("Failed to persist active_identity (err %d)", err);
}
#endif
#if IS_ENABLED(CONFIG_BT_DEVICE_NAME_DYNAMIC)
char name[CONFIG_BT_DEVICE_NAME_MAX];
snprintf(name, sizeof(name), "%s (Profile %d)", CONFIG_ZMK_KEYBOARD_NAME, active_identity + 1);
bt_set_name(name);
#endif /* IS_ENABLED(CONFIG_BT_DEVICE_NAME_DYNAMIC) */
}
return zmk_ble_adv_resume();
};
static int deactivate_profile(u8_t index)
{
int err = zmk_ble_adv_pause();
if (err) {
LOG_WRN("Failed to pause advertising %d", err);
}
bt_conn_foreach(BT_CONN_TYPE_ALL, disconnect_host_connection, NULL);
return 0;
};
int zmk_ble_identity_select(u8_t index)
{
LOG_DBG("index %d", index);
if (index >= IDENTITY_COUNT) {
return -EINVAL;
}
int err = deactivate_profile(active_identity);
if (err) {
LOG_WRN("Failed to deactivate profile");
return err;
}
return activate_profile(index);
};
static void unpair_non_peripheral_bonds(const struct bt_bond_info *info, void *user_data) { static void unpair_non_peripheral_bonds(const struct bt_bond_info *info, void *user_data) {
char addr[BT_ADDR_LE_STR_LEN]; char addr[BT_ADDR_LE_STR_LEN];
@ -200,34 +140,19 @@ static void unpair_non_peripheral_bonds(const struct bt_bond_info *info, void *u
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */ #endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
LOG_DBG("Unpairing %s", log_strdup(addr)); LOG_DBG("Unpairing %s", log_strdup(addr));
bt_unpair(active_identity, &info->addr); bt_unpair(BT_ID_DEFAULT, &info->addr);
} }
int zmk_ble_identity_clear() int zmk_ble_clear_bonds()
{ {
LOG_DBG(""); LOG_DBG("");
int err = deactivate_profile(active_identity);
if (err) {
return err;
}
bt_foreach_bond(active_identity, unpair_non_peripheral_bonds, NULL); bt_conn_foreach(BT_ID_DEFAULT, disconnect_host_connection, NULL);
bt_foreach_bond(BT_ID_DEFAULT, unpair_non_peripheral_bonds, NULL);
return activate_profile(active_identity); return 0;
}; };
int zmk_ble_identity_next()
{
LOG_DBG("active_identity %d IDENTITY_COUNT %d", active_identity, IDENTITY_COUNT);
return zmk_ble_identity_select((active_identity + 1) % IDENTITY_COUNT);
}
int zmk_ble_identity_prev()
{
LOG_DBG("");
return zmk_ble_identity_select((active_identity + IDENTITY_COUNT - 1) % IDENTITY_COUNT);
}
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) #if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr) void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr)
@ -246,19 +171,8 @@ static int ble_profiles_handle_set(const char *name, size_t len, settings_read_c
LOG_DBG("Setting BLE value %s", log_strdup(name)); LOG_DBG("Setting BLE value %s", log_strdup(name));
if (settings_name_steq(name, "active_identity", &next) && !next) {
if (len != sizeof(active_identity)) {
return -EINVAL;
}
int err = read_cb(cb_arg, &active_identity, sizeof(active_identity));
if (err <= 0) {
LOG_ERR("Failed to handle profile from settings (err %d)", err);
return err;
}
LOG_DBG("Loaded active identity %d", active_identity);
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) #if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
} else if (settings_name_steq(name, "peripheral_address", &next) && !next) { if (settings_name_steq(name, "peripheral_address", &next) && !next) {
if (len != sizeof(bt_addr_le_t)) { if (len != sizeof(bt_addr_le_t)) {
return -EINVAL; return -EINVAL;
} }
@ -268,8 +182,8 @@ static int ble_profiles_handle_set(const char *name, size_t len, settings_read_c
LOG_ERR("Failed to handle peripheral address from settings (err %d)", err); LOG_ERR("Failed to handle peripheral address from settings (err %d)", err);
return err; return err;
} }
#endif
} }
#endif
return 0; return 0;
}; };
@ -318,6 +232,8 @@ static void disconnected(struct bt_conn *conn, u8_t reason)
if (bt_addr_le_cmp(&peripheral_addr, BT_ADDR_LE_ANY) && bt_addr_le_cmp(&peripheral_addr, bt_conn_get_dst(conn))) { if (bt_addr_le_cmp(&peripheral_addr, BT_ADDR_LE_ANY) && bt_addr_le_cmp(&peripheral_addr, bt_conn_get_dst(conn))) {
zmk_ble_adv_resume(); zmk_ble_adv_resume();
} }
#else
zmk_ble_adv_resume();
#endif #endif
} }
@ -404,42 +320,12 @@ static void zmk_ble_ready(int err)
return; return;
} }
zmk_ble_identity_select(active_identity); zmk_ble_adv_resume();
} }
#if CONFIG_BT_ID_MAX != 1
static int initialize_identities()
{
bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
size_t count = CONFIG_BT_ID_MAX;
LOG_DBG("");
bt_id_get(addrs, &count);
for (int i = 0; i < count; i++) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(&addrs[i], addr, sizeof(addr));
LOG_DBG("Existing identity %s", log_strdup(addr));
}
for (int i = count; i < CONFIG_BT_ID_MAX; i++) {
LOG_DBG("Initializing identity %d", i);
int id = bt_id_create(NULL, NULL);
if (id < 0) {
LOG_ERR("Failed to create new identity with id %d", i);
return id;
}
}
return 0;
};
#endif /* CONFIG_BT_ID_MAX != 1 */
static int zmk_ble_init(struct device *_arg) static int zmk_ble_init(struct device *_arg)
{ {
int err; int err = bt_enable(NULL);
err = bt_enable(NULL);
if (err) if (err)
{ {
@ -460,10 +346,6 @@ static int zmk_ble_init(struct device *_arg)
#endif #endif
#if CONFIG_BT_ID_MAX != 1
initialize_identities();
#endif /* CONFIG_BT_ID_MAX != 1 */
bt_conn_cb_register(&conn_callbacks); bt_conn_cb_register(&conn_callbacks);
bt_conn_auth_cb_register(&zmk_ble_auth_cb_display); bt_conn_auth_cb_register(&zmk_ble_auth_cb_display);
@ -474,13 +356,17 @@ static int zmk_ble_init(struct device *_arg)
int zmk_ble_unpair_all() int zmk_ble_unpair_all()
{ {
LOG_DBG(""); int resp = 0;
int err = bt_unpair(BT_ID_DEFAULT, NULL); for (int i = BT_ID_DEFAULT; i < CONFIG_BT_ID_MAX; i++) {
if (err) {
LOG_ERR("Failed to unpair devices (err %d)", err); int err = bt_unpair(BT_ID_DEFAULT, NULL);
if (err) {
resp = err;
LOG_ERR("Failed to unpair devices (err %d)", err);
}
} }
return err; return resp;
}; };
bool zmk_ble_handle_key_user(struct zmk_key_event *key_event) bool zmk_ble_handle_key_user(struct zmk_key_event *key_event)

1
app/src/split_listener.c

@ -21,6 +21,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
int split_listener(const struct zmk_event_header *eh) int split_listener(const struct zmk_event_header *eh)
{ {
LOG_DBG("");
if (is_position_state_changed(eh)) { if (is_position_state_changed(eh)) {
const struct position_state_changed *ev = cast_position_state_changed(eh); const struct position_state_changed *ev = cast_position_state_changed(eh);
if (ev->state) { if (ev->state) {

58
docs/docs/behavior/bluetooth.md

@ -6,7 +6,8 @@ sidebar_label: Bluetooth
## Summary ## Summary
The bluetooth behavior allows management of various settings and states related to the bluetooth connection(s) The bluetooth behavior allows management of various settings and states related to the bluetooth connection(s)
between the keyboard and the host. between the keyboard and the host. As of right now, there is only one such action support, but in the future
more will be added.
## Bluetooth Command Defines ## Bluetooth Command Defines
@ -17,31 +18,20 @@ which is added at the top of the keymap file:
#include <dt-bindings/zmk/bt.h> #include <dt-bindings/zmk/bt.h>
``` ```
This will allow you to reference the actions defined in this header such as `BT_IDENT_CLR_CMD`. This will allow you to reference the actions defined in this header such as `BT_CLEAR_BONDS_CMD`.
Here is a table describing the command for each define: Here is a table describing the command for each define:
| Define | Action | | Define | Action |
| ------------------- | ----------------------------------------------------- | | -------------------- | --------------------------------------------------------- |
| `BT_IDENT_CLR_CMD` | Clear paired keyboards (for the current identity)[^1] | | `BT_CLEAR_BONDS_CMD` | Clear bond information between the keyboard and host [^1] |
| `BT_IDENT_NEXT_CMD` | Switch to the next identity[^1] |
| `BT_IDENT_PREV_CMD` | Switch to the previous identity |
| `BT_IDENT_SEL_CMD` | Switch to a specific numbered identity |
| `BT_RST_CMD` | Hard reset of all bluetooth bonds |
Because the `BT_IDENT_SEL_CMD` command takes an additional parameter, the numeric index of the identity to select, _all_ the commands for the bluetooth behavior must take that additional parameter, and ignore the value. To make this easier, Because future bluetooth commands will take an additional parameter, it is recommended to use
there are alias defines that add those default parameters for you: the following alias in your keymap to avoid having to change it later.
| Define | Action | | Define | Action |
| --------------- | --------------------------------------------------------------------------------------- | | ---------------- | ---------------------------------------------------------------------- |
| `BT_IDENT_CLR` | Alias for `BT_IDENT_CLR_CMD 0` to clear paired keyboards (for the current identity)[^1] | | `BT_CLEAR_BONDS` | Alias for `BT_CLEAR_BONDS_CMD 0` to clear the bond to the current host |
| `BT_IDENT_NEXT` | Alias for `BT_IDENT_NEXT_CMD 0` to switch to the next identity[^1] |
| `BT_IDENT_PREV` | Alias for `BT_IDENT_PREV_CMD 0` to switch to the previous identity |
| `BT_IDENT_SEL` | Alias for `BT_IDENT_SEL_CMD` to switch to a specific numbered identity |
| `BT_RST` | Alias for `BT_RST_CMD 0` to reset all bonds[^2] |
[^1]: Multiple keyboard identities/profiles is only support on non-split keyboards as of this time.
[^2]: This may interrupt pairing between both halves of a split keyboard. For split keyboards, it is preferred to use the [/docs/bond-reset] combo to clear bonds on both devices
## Bluetooth Behavior ## Bluetooth Behavior
@ -50,33 +40,13 @@ The bluetooth behavior completes an bluetooth action given on press.
### Behavior Binding ### Behavior Binding
- Reference: `&bt` - Reference: `&bt`
- Parameter #1: The bluetooth command define, e.g. `BT_IDENT_CLR_CMD` or `BT_RST_CMD` - Parameter #1: The bluetooth command define, e.g. `BT_CLEAR_BONDS_CMD`
- Parameter #2: The parameter for the command, when used to identify an identity/profile to select, e.g. `0` - Parameter #2: (Reserved for future bluetooth command types)
### Examples ### Examples
1. Behavior to clear the paired host: 1. Behavior to clear the paired host:
``` ```
&bt BT_IDENT_CLR &bt BT_CLEAR_BONDS
```
1. Behavior to hard reset all bonded devices[^2]:
```
&bt BT_IDENT_CLR
```
Examples for non-split keyboards with multiple identities:
1. Behavior to switch to the next identity:
```
&bt BT_IDENT_NEXT
```
1. Behavior to switch to the specific numbered identity:
```
&bt BT_IDENT_SEL 1
``` ```

Loading…
Cancel
Save