diff --git a/app/include/zmk/ble.h b/app/include/zmk/ble.h index f6f6e191..0bdbab38 100644 --- a/app/include/zmk/ble.h +++ b/app/include/zmk/ble.h @@ -21,8 +21,7 @@ bool zmk_ble_active_profile_is_connected(); char *zmk_ble_active_profile_name(); int zmk_ble_unpair_all(); -bool zmk_ble_handle_key_user(struct zmk_key_event *key_event); #if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr); -#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */ \ No newline at end of file +#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */ diff --git a/app/src/ble.c b/app/src/ble.c index a9f2afe9..68061129 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -36,10 +36,24 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include +#define IS_HOST_PERIPHERAL \ + (!IS_ENABLED(CONFIG_ZMK_SPLIT) || IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)) +#define IS_SPLIT_PERIPHERAL \ + (IS_ENABLED(CONFIG_ZMK_SPLIT) && !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)) + +#define DO_PASSKEY_ENTRY (IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) && !IS_SPLIT_PERIPHERAL) + +#if DO_PASSKEY_ENTRY +#include + +#define PASSKEY_DIGITS 6 + static struct bt_conn *auth_passkey_entry_conn; -static uint8_t passkey_entries[6] = {0, 0, 0, 0, 0, 0}; +static uint8_t passkey_entries[PASSKEY_DIGITS] = {}; static uint8_t passkey_digit = 0; +#endif + #if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) #define PROFILE_COUNT (CONFIG_BT_MAX_PAIRED - 1) #else @@ -66,11 +80,6 @@ static uint8_t active_profile; BUILD_ASSERT(DEVICE_NAME_LEN <= 16, "ERROR: BLE device name is too long. Max length: 16"); -#define IS_HOST_PERIPHERAL \ - (!IS_ENABLED(CONFIG_ZMK_SPLIT) || IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)) -#define IS_SPLIT_PERIPHERAL \ - (IS_ENABLED(CONFIG_ZMK_SPLIT) && !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)) - static const struct bt_data zmk_ble_ad[] = { #if IS_HOST_PERIPHERAL BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), @@ -456,7 +465,7 @@ static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey) { } */ -#ifdef CONFIG_ZMK_BLE_PASSKEY_ENTRY +#if DO_PASSKEY_ENTRY static void auth_passkey_entry(struct bt_conn *conn) { char addr[BT_ADDR_LE_STR_LEN]; @@ -464,6 +473,7 @@ static void auth_passkey_entry(struct bt_conn *conn) { bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_DBG("Passkey entry requested for %s", log_strdup(addr)); + passkey_digit = 0; auth_passkey_entry_conn = bt_conn_ref(conn); } @@ -474,12 +484,14 @@ static void auth_cancel(struct bt_conn *conn) { bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); +#if DO_PASSKEY_ENTRY if (auth_passkey_entry_conn) { bt_conn_unref(auth_passkey_entry_conn); auth_passkey_entry_conn = NULL; } passkey_digit = 0; +#endif LOG_DBG("Pairing cancelled: %s", log_strdup(addr)); } @@ -532,7 +544,7 @@ static struct bt_conn_auth_cb zmk_ble_auth_cb_display = { .pairing_complete = auth_pairing_complete, // .passkey_display = auth_passkey_display, -#ifdef CONFIG_ZMK_BLE_PASSKEY_ENTRY +#if DO_PASSKEY_ENTRY .passkey_entry = auth_passkey_entry, #endif .cancel = auth_cancel, @@ -612,32 +624,79 @@ int zmk_ble_unpair_all() { return resp; }; -bool zmk_ble_handle_key_user(struct zmk_key_event *key_event) { - zmk_key_t key = key_event->key; +#if DO_PASSKEY_ENTRY + +static bool zmk_ble_numeric_usage_to_value(const zmk_key_t key, const zmk_key_t one, + const zmk_key_t zero, uint32_t *value) { + if (key < one || key > zero) { + return false; + } + + *value = (key == zero) ? 0 : (key - one + 1); + return true; +} + +static int zmk_ble_handle_key_user(struct zmk_keycode_state_changed *event) { + zmk_key_t key = event->keycode; + + LOG_DBG("key %d", key); if (!auth_passkey_entry_conn) { - return true; + LOG_DBG("No connection for passkey entry"); + return ZMK_EV_EVENT_BUBBLE; + } + + if (!event->state) { + LOG_DBG("Key released, ignoring"); + return ZMK_EV_EVENT_BUBBLE; } - if (key < NUMBER_1 || key > NUMBER_0) { - return true; + if (key == HID_USAGE_KEY_KEYBOARD_ESCAPE) { + bt_conn_auth_cancel(auth_passkey_entry_conn); + return ZMK_EV_EVENT_HANDLED; } - uint32_t val = (key == NUMBER_0) ? 0 : (key - NUMBER_1 + 1); + uint32_t val; + if (!(zmk_ble_numeric_usage_to_value(key, HID_USAGE_KEY_KEYBOARD_1_AND_EXCLAMATION, + HID_USAGE_KEY_KEYBOARD_0_AND_RIGHT_PARENTHESIS, &val) || + zmk_ble_numeric_usage_to_value(key, HID_USAGE_KEY_KEYPAD_1_AND_END, + HID_USAGE_KEY_KEYPAD_0_AND_INSERT, &val))) { + LOG_DBG("Key not a number, ignoring"); + return ZMK_EV_EVENT_BUBBLE; + } passkey_entries[passkey_digit++] = val; + LOG_DBG("value entered: %d, digits collected so far: %d", val, passkey_digit); - if (passkey_digit == 6) { + if (passkey_digit == PASSKEY_DIGITS) { uint32_t passkey = 0; - for (int i = 5; i >= 0; i--) { - passkey = (passkey * 10) + val; + for (int i = 0; i < PASSKEY_DIGITS; i++) { + passkey = (passkey * 10) + passkey_entries[i]; } + + LOG_DBG("Final passkey: %d", passkey); bt_conn_auth_passkey_entry(auth_passkey_entry_conn, passkey); bt_conn_unref(auth_passkey_entry_conn); auth_passkey_entry_conn = NULL; } - return false; + return ZMK_EV_EVENT_HANDLED; } +static int zmk_ble_listener(const zmk_event_t *eh) { + struct zmk_keycode_state_changed *kc_state; + + kc_state = as_zmk_keycode_state_changed(eh); + + if (kc_state != NULL) { + return zmk_ble_handle_key_user(kc_state); + } + + return 0; +} + +ZMK_LISTENER(zmk_ble, zmk_ble_listener); +ZMK_SUBSCRIPTION(zmk_ble, zmk_keycode_state_changed); +#endif /* DO_PASSKEY_ENTRY */ + SYS_INIT(zmk_ble_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);