diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 5e1bd88a..054f84a7 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -44,6 +44,7 @@ target_sources(app PRIVATE src/behaviors/behavior_none.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_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/bluetooth/service.c) target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL app PRIVATE src/split/bluetooth/central.c) diff --git a/app/Kconfig b/app/Kconfig index b26be487..416c9852 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -40,11 +40,17 @@ menuconfig ZMK_BLE select BT_PERIPHERAL select BT_GATT_DIS select BT_GATT_BAS - # select SETTINGS - # select BT_SETTINGS + select SETTINGS + select BT_SETTINGS 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 int "Init Priority" default 50 diff --git a/app/boards/shields/corne/corne.dtsi b/app/boards/shields/corne/corne.dtsi index 70d6495b..3df055cd 100644 --- a/app/boards/shields/corne/corne.dtsi +++ b/app/boards/shields/corne/corne.dtsi @@ -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)? }; diff --git a/app/boards/shields/corne/corne_left.conf b/app/boards/shields/corne/corne_left.conf index e51dee44..338fa59c 100644 --- a/app/boards/shields/corne/corne_left.conf +++ b/app/boards/shields/corne/corne_left.conf @@ -1,2 +1,3 @@ CONFIG_ZMK_SPLIT=y -CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y \ No newline at end of file +CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y +CONFIG_ZMK_BLE_UNPAIR_COMBO=y \ No newline at end of file diff --git a/app/boards/shields/corne/corne_left.overlay b/app/boards/shields/corne/corne_left.overlay index 399bddd1..f12c417d 100644 --- a/app/boards/shields/corne/corne_left.overlay +++ b/app/boards/shields/corne/corne_left.overlay @@ -16,3 +16,7 @@ , <&pro_micro_d 14 GPIO_ACTIVE_HIGH> ; }; + +&bt_unpair_combo { + key-positions = <0 38>; +}; diff --git a/app/boards/shields/corne/corne_right.conf b/app/boards/shields/corne/corne_right.conf index a835adc1..be344c41 100644 --- a/app/boards/shields/corne/corne_right.conf +++ b/app/boards/shields/corne/corne_right.conf @@ -1,2 +1,3 @@ CONFIG_ZMK_SPLIT=y -CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y \ No newline at end of file +CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y +CONFIG_ZMK_BLE_UNPAIR_COMBO=y \ No newline at end of file diff --git a/app/boards/shields/corne/corne_right.overlay b/app/boards/shields/corne/corne_right.overlay index 652d5edd..9d97d853 100644 --- a/app/boards/shields/corne/corne_right.overlay +++ b/app/boards/shields/corne/corne_right.overlay @@ -21,3 +21,6 @@ ; }; +&bt_unpair_combo { + key-positions = <11 39>; +}; diff --git a/app/boards/shields/kyria/kyria.dtsi b/app/boards/shields/kyria/kyria.dtsi index bbead846..a13f7f08 100644 --- a/app/boards/shields/kyria/kyria.dtsi +++ b/app/boards/shields/kyria/kyria.dtsi @@ -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>; }; + bt_unpair_combo: bt_unpair_combo { + compatible = "zmk,bt-unpair-combo"; + }; + // TODO: RGB node(s) }; diff --git a/app/boards/shields/kyria/kyria_left.conf b/app/boards/shields/kyria/kyria_left.conf index e51dee44..338fa59c 100644 --- a/app/boards/shields/kyria/kyria_left.conf +++ b/app/boards/shields/kyria/kyria_left.conf @@ -1,2 +1,3 @@ CONFIG_ZMK_SPLIT=y -CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y \ No newline at end of file +CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y +CONFIG_ZMK_BLE_UNPAIR_COMBO=y \ No newline at end of file diff --git a/app/boards/shields/kyria/kyria_left.overlay b/app/boards/shields/kyria/kyria_left.overlay index c8b5be27..441c1a69 100644 --- a/app/boards/shields/kyria/kyria_left.overlay +++ b/app/boards/shields/kyria/kyria_left.overlay @@ -22,3 +22,7 @@ &left_encoder { status = "okay"; }; + +&bt_unpair_combo { + key-positions = <0 44>; +}; \ No newline at end of file diff --git a/app/boards/shields/kyria/kyria_right.conf b/app/boards/shields/kyria/kyria_right.conf index a835adc1..be344c41 100644 --- a/app/boards/shields/kyria/kyria_right.conf +++ b/app/boards/shields/kyria/kyria_right.conf @@ -1,2 +1,3 @@ CONFIG_ZMK_SPLIT=y -CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y \ No newline at end of file +CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y +CONFIG_ZMK_BLE_UNPAIR_COMBO=y \ No newline at end of file diff --git a/app/boards/shields/kyria/kyria_right.overlay b/app/boards/shields/kyria/kyria_right.overlay index 8163c95e..8ee0fcbc 100644 --- a/app/boards/shields/kyria/kyria_right.overlay +++ b/app/boards/shields/kyria/kyria_right.overlay @@ -27,3 +27,7 @@ &right_encoder { status = "okay"; }; + +&bt_unpair_combo { + key-positions = <11 45>; +}; \ No newline at end of file diff --git a/app/boards/shields/lily58/lily58.dtsi b/app/boards/shields/lily58/lily58.dtsi index 8655d8c0..cbda5237 100644 --- a/app/boards/shields/lily58/lily58.dtsi +++ b/app/boards/shields/lily58/lily58.dtsi @@ -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 { diff --git a/app/boards/shields/lily58/lily58_left.conf b/app/boards/shields/lily58/lily58_left.conf index e51dee44..338fa59c 100644 --- a/app/boards/shields/lily58/lily58_left.conf +++ b/app/boards/shields/lily58/lily58_left.conf @@ -1,2 +1,3 @@ CONFIG_ZMK_SPLIT=y -CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y \ No newline at end of file +CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y +CONFIG_ZMK_BLE_UNPAIR_COMBO=y \ No newline at end of file diff --git a/app/boards/shields/lily58/lily58_left.overlay b/app/boards/shields/lily58/lily58_left.overlay index c8e22130..c6f630f8 100644 --- a/app/boards/shields/lily58/lily58_left.overlay +++ b/app/boards/shields/lily58/lily58_left.overlay @@ -17,3 +17,6 @@ ; }; +&bt_unpair_combo { + key-positions = <0 42>; +}; diff --git a/app/boards/shields/lily58/lily58_right.conf b/app/boards/shields/lily58/lily58_right.conf index 990cf7c0..cf16779e 100644 --- a/app/boards/shields/lily58/lily58_right.conf +++ b/app/boards/shields/lily58/lily58_right.conf @@ -1,2 +1,3 @@ CONFIG_ZMK_SPLIT=y CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y +CONFIG_ZMK_BLE_UNPAIR_COMBO=y diff --git a/app/boards/shields/lily58/lily58_right.overlay b/app/boards/shields/lily58/lily58_right.overlay index 748be145..84f0b06b 100644 --- a/app/boards/shields/lily58/lily58_right.overlay +++ b/app/boards/shields/lily58/lily58_right.overlay @@ -21,3 +21,6 @@ ; }; +&bt_unpair_combo { + key-positions = <11 43>; +}; diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c index baaca309..b19c4922 100644 --- a/app/drivers/zephyr/kscan_gpio_matrix.c +++ b/app/drivers/zephyr/kscan_gpio_matrix.c @@ -205,7 +205,13 @@ static int kscan_gpio_config_interrupts(struct device **devices, } \ data->callback = callback; \ 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) \ { \ 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 = { \ .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, \ }; \ static const struct kscan_gpio_config_##n kscan_gpio_config_##n = { \ diff --git a/app/dts/bindings/zmk,bt-unpair-combo.yaml b/app/dts/bindings/zmk,bt-unpair-combo.yaml new file mode 100644 index 00000000..d781347a --- /dev/null +++ b/app/dts/bindings/zmk,bt-unpair-combo.yaml @@ -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 diff --git a/app/include/zmk/ble.h b/app/include/zmk/ble.h index a77237d8..e760ed70 100644 --- a/app/include/zmk/ble.h +++ b/app/include/zmk/ble.h @@ -3,5 +3,5 @@ #include -int zmk_ble_init(); +int zmk_ble_unpair_all(); bool zmk_ble_handle_key_user(struct zmk_key_event *key_event); diff --git a/app/src/ble.c b/app/src/ble.c index bf1dee74..0e96d16a 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -200,6 +200,12 @@ static int zmk_ble_init(struct device *_arg) 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) { zmk_key key = key_event->key; diff --git a/app/src/ble_unpair_combo.c b/app/src/ble_unpair_combo.c new file mode 100644 index 00000000..a33a8e22 --- /dev/null +++ b/app/src/ble_unpair_combo.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020 Peter Johanson + * + * SPDX-License-Identifier: MIT + */ + +#include +#include + +#include + +#define DT_DRV_COMPAT zmk_bt_unpair_combo + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#include +#include +#include + + +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);