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:
parent
d7dee20e8d
commit
4402e4fbc7
22 changed files with 160 additions and 10 deletions
|
@ -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)
|
||||||
|
|
10
app/Kconfig
10
app/Kconfig
|
@ -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
|
||||||
|
|
|
@ -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)?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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>;
|
||||||
|
};
|
||||||
|
|
|
@ -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
|
|
@ -21,3 +21,6 @@
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&bt_unpair_combo {
|
||||||
|
key-positions = <11 39>;
|
||||||
|
};
|
||||||
|
|
|
@ -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)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -22,3 +22,7 @@
|
||||||
&left_encoder {
|
&left_encoder {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&bt_unpair_combo {
|
||||||
|
key-positions = <0 44>;
|
||||||
|
};
|
|
@ -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
|
|
@ -27,3 +27,7 @@
|
||||||
&right_encoder {
|
&right_encoder {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&bt_unpair_combo {
|
||||||
|
key-positions = <11 45>;
|
||||||
|
};
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
|
@ -17,3 +17,6 @@
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&bt_unpair_combo {
|
||||||
|
key-positions = <0 42>;
|
||||||
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -21,3 +21,6 @@
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&bt_unpair_combo {
|
||||||
|
key-positions = <11 43>;
|
||||||
|
};
|
||||||
|
|
|
@ -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 = { \
|
||||||
|
|
12
app/dts/bindings/zmk,bt-unpair-combo.yaml
Normal file
12
app/dts/bindings/zmk,bt-unpair-combo.yaml
Normal 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
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
80
app/src/ble_unpair_combo.c
Normal file
80
app/src/ble_unpair_combo.c
Normal 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);
|
Loading…
Reference in a new issue