feeature(bt): Add "unpair combo" on startup.

* Especially for splits, we need the ability to
  unpair all paired devices as  sledgehammer
  if we need to "reset things", and doing so via
  keymaps isn't suitable.
* Allows shields to define a collection of key
  positions that if all held 2 seconds after
  startup, will unpair all existing pairs for the
  device.
This commit is contained in:
Pete Johanson 2020-08-18 11:20:15 -04:00
parent d7dee20e8d
commit 4402e4fbc7
22 changed files with 160 additions and 10 deletions

View file

@ -42,6 +42,7 @@ target_sources(app PRIVATE src/behaviors/behavior_transparent.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)
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/ble.c) target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble.c)
target_sources_ifdef(CONFIG_ZMK_BLE_UNPAIR_COMBO app PRIVATE src/ble_unpair_combo.c)
target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL app PRIVATE src/split_listener.c) target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL app PRIVATE src/split_listener.c)
target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL app PRIVATE src/split/bluetooth/service.c) target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL app PRIVATE src/split/bluetooth/service.c)
target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL app PRIVATE src/split/bluetooth/central.c) target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL app PRIVATE src/split/bluetooth/central.c)

View file

@ -40,11 +40,17 @@ 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 SETTINGS select SETTINGS
# select BT_SETTINGS select BT_SETTINGS
if ZMK_BLE if ZMK_BLE
config ZMK_BLE_UNPAIR_COMBO
bool "Enable BT unpair combo"
help
Adds a magic key combo that can be held on startup to remove all paired devices
default n
config ZMK_BLE_INIT_PRIORITY config ZMK_BLE_INIT_PRIORITY
int "Init Priority" int "Init Priority"
default 50 default 50

View file

@ -58,6 +58,10 @@ RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10
}; };
bt_unpair_combo: bt_unpair_combo {
compatible = "zmk,bt-unpair-combo";
};
// TODO: per-key RGB node(s)? // TODO: per-key RGB node(s)?
}; };

View file

@ -1,2 +1,3 @@
CONFIG_ZMK_SPLIT=y CONFIG_ZMK_SPLIT=y
CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
CONFIG_ZMK_BLE_UNPAIR_COMBO=y

View file

@ -16,3 +16,7 @@
, <&pro_micro_d 14 GPIO_ACTIVE_HIGH> , <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
; ;
}; };
&bt_unpair_combo {
key-positions = <0 38>;
};

View file

@ -1,2 +1,3 @@
CONFIG_ZMK_SPLIT=y CONFIG_ZMK_SPLIT=y
CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y
CONFIG_ZMK_BLE_UNPAIR_COMBO=y

View file

@ -21,3 +21,6 @@
; ;
}; };
&bt_unpair_combo {
key-positions = <11 39>;
};

View file

@ -81,6 +81,10 @@ RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9)
sensors = <&left_encoder &right_encoder>; sensors = <&left_encoder &right_encoder>;
}; };
bt_unpair_combo: bt_unpair_combo {
compatible = "zmk,bt-unpair-combo";
};
// TODO: RGB node(s) // TODO: RGB node(s)
}; };

View file

@ -1,2 +1,3 @@
CONFIG_ZMK_SPLIT=y CONFIG_ZMK_SPLIT=y
CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
CONFIG_ZMK_BLE_UNPAIR_COMBO=y

View file

@ -22,3 +22,7 @@
&left_encoder { &left_encoder {
status = "okay"; status = "okay";
}; };
&bt_unpair_combo {
key-positions = <0 44>;
};

View file

@ -1,2 +1,3 @@
CONFIG_ZMK_SPLIT=y CONFIG_ZMK_SPLIT=y
CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y
CONFIG_ZMK_BLE_UNPAIR_COMBO=y

View file

@ -27,3 +27,7 @@
&right_encoder { &right_encoder {
status = "okay"; status = "okay";
}; };
&bt_unpair_combo {
key-positions = <11 45>;
};

View file

@ -44,6 +44,10 @@ RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,5) RC(4,6) RC(3,6) RC(3,7)
; ;
}; };
bt_unpair_combo: bt_unpair_combo {
compatible = "zmk,bt-unpair-combo";
};
}; };
&pro_micro_i2c { &pro_micro_i2c {

View file

@ -1,2 +1,3 @@
CONFIG_ZMK_SPLIT=y CONFIG_ZMK_SPLIT=y
CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
CONFIG_ZMK_BLE_UNPAIR_COMBO=y

View file

@ -17,3 +17,6 @@
; ;
}; };
&bt_unpair_combo {
key-positions = <0 42>;
};

View file

@ -1,2 +1,3 @@
CONFIG_ZMK_SPLIT=y CONFIG_ZMK_SPLIT=y
CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y
CONFIG_ZMK_BLE_UNPAIR_COMBO=y

View file

@ -21,3 +21,6 @@
; ;
}; };
&bt_unpair_combo {
key-positions = <11 43>;
};

View file

@ -205,7 +205,13 @@ static int kscan_gpio_config_interrupts(struct device **devices,
} \ } \
data->callback = callback; \ data->callback = callback; \
return 0; \ return 0; \
} \ }; \
static int kscan_gpio_enable_##n(struct device *dev) \
{ \
int err = kscan_gpio_enable_interrupts_##n(dev); \
if (err) { return err; } \
return kscan_gpio_read_##n(dev); \
}; \
static int kscan_gpio_init_##n(struct device *dev) \ static int kscan_gpio_init_##n(struct device *dev) \
{ \ { \
struct kscan_gpio_data_##n *data = dev->driver_data; \ struct kscan_gpio_data_##n *data = dev->driver_data; \
@ -258,7 +264,7 @@ static int kscan_gpio_config_interrupts(struct device **devices,
} \ } \
static const struct kscan_driver_api gpio_driver_api_##n = { \ static const struct kscan_driver_api gpio_driver_api_##n = { \
.config = kscan_gpio_configure_##n, \ .config = kscan_gpio_configure_##n, \
.enable_callback = kscan_gpio_enable_interrupts_##n, \ .enable_callback = kscan_gpio_enable_##n, \
.disable_callback = kscan_gpio_disable_interrupts_##n, \ .disable_callback = kscan_gpio_disable_interrupts_##n, \
}; \ }; \
static const struct kscan_gpio_config_##n kscan_gpio_config_##n = { \ static const struct kscan_gpio_config_##n kscan_gpio_config_##n = { \

View file

@ -0,0 +1,12 @@
# Copyright (c) 2020, Pete Johanson
# SPDX-License-Identifier: MIT
description: |
Defines a set of key positions that will unpair all BT devices if held on startup.
compatible: "zmk,bt-unpair-combo"
properties:
key-positions:
type: array
required: true

View file

@ -3,5 +3,5 @@
#include <zmk/keys.h> #include <zmk/keys.h>
int zmk_ble_init(); 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);

View file

@ -190,6 +190,12 @@ static int zmk_ble_init(struct device *_arg)
return 0; return 0;
} }
int zmk_ble_unpair_all()
{
LOG_DBG("");
return bt_unpair(BT_ID_DEFAULT, NULL);
};
bool zmk_ble_handle_key_user(struct zmk_key_event *key_event) bool zmk_ble_handle_key_user(struct zmk_key_event *key_event)
{ {
zmk_key key = key_event->key; zmk_key key = key_event->key;

View file

@ -0,0 +1,80 @@
/*
* Copyright (c) 2020 Peter Johanson
*
* SPDX-License-Identifier: MIT
*/
#include <device.h>
#include <init.h>
#include <logging/log.h>
#define DT_DRV_COMPAT zmk_bt_unpair_combo
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/ble.h>
#include <zmk/event-manager.h>
#include <zmk/events/position-state-changed.h>
static u8_t combo_state;
const u32_t key_positions[] = DT_INST_PROP(0, key_positions);
#define KP_LEN DT_INST_PROP_LEN(0, key_positions)
int index_for_key_position(u32_t kp)
{
for (int i = 0; i < KP_LEN; i++) {
if (key_positions[i] == kp) {
return i;
}
}
return -1;
}
int unpair_combo_listener(const struct zmk_event_header *eh)
{
if (is_position_state_changed(eh)) {
const struct position_state_changed *psc = cast_position_state_changed(eh);
int kp_index = index_for_key_position(psc->position);
if (kp_index < 0) {
return 0;
}
WRITE_BIT(combo_state, kp_index, psc->state);
}
return 0;
};
void unpair_combo_work_handler(struct k_work *work)
{
for (int i = 0; i < KP_LEN; i++) {
if (!(combo_state & BIT(i))) {
LOG_DBG("Key position %d not held, skipping unpair combo", key_positions[i]);
return;
}
}
zmk_ble_unpair_all();
};
struct k_delayed_work unpair_combo_work;
int zmk_ble_unpair_combo_init(struct device *_unused)
{
k_delayed_work_init(&unpair_combo_work, unpair_combo_work_handler);
k_delayed_work_submit(&unpair_combo_work, K_SECONDS(2));
return 0;
};
ZMK_LISTENER(zmk_ble_unpair_combo, unpair_combo_listener);
ZMK_SUBSCRIPTION(zmk_ble_unpair_combo, position_state_changed);
SYS_INIT(zmk_ble_unpair_combo_init,
APPLICATION,
CONFIG_APPLICATION_INIT_PRIORITY);