Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(bluetooth): Passkey pairing improvements. #1822

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/Kconfig
Expand Up @@ -160,8 +160,9 @@ config BT_DEVICE_APPEARANCE
default 961

config ZMK_BLE_PASSKEY_ENTRY
bool "Experimental: Requiring typing passkey from host to pair BLE connection"
bool "Require passkey entry on the keyboard to complete pairing"
default n
select RING_BUFFER

config BT_PERIPHERAL_PREF_MIN_INT
default 6
Expand Down
47 changes: 28 additions & 19 deletions app/src/ble.c
Expand Up @@ -13,6 +13,7 @@
#include <stdio.h>

#include <zephyr/settings/settings.h>
#include <zephyr/sys/ring_buffer.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/hci.h>
Expand Down Expand Up @@ -42,8 +43,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#define PASSKEY_DIGITS 6

static struct bt_conn *auth_passkey_entry_conn;
static uint8_t passkey_entries[PASSKEY_DIGITS] = {};
static uint8_t passkey_digit = 0;
RING_BUF_DECLARE(passkey_entries, PASSKEY_DIGITS);

#endif /* IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) */

Expand Down Expand Up @@ -469,7 +469,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", addr);
passkey_digit = 0;
ring_buf_reset(&passkey_entries);
auth_passkey_entry_conn = bt_conn_ref(conn);
}

Expand All @@ -486,7 +486,7 @@ static void auth_cancel(struct bt_conn *conn) {
auth_passkey_entry_conn = NULL;
}

passkey_digit = 0;
ring_buf_reset(&passkey_entries);
#endif

LOG_DBG("Pairing cancelled: %s", addr);
Expand Down Expand Up @@ -605,7 +605,7 @@ static int zmk_ble_init(const struct device *_arg) {
#if IS_ENABLED(CONFIG_ZMK_BLE_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) {
const zmk_key_t zero, uint8_t *value) {
if (key < one || key > zero) {
return false;
}
Expand Down Expand Up @@ -634,29 +634,38 @@ static int zmk_ble_handle_key_user(struct zmk_keycode_state_changed *event) {
return ZMK_EV_EVENT_HANDLED;
}

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 (key == HID_USAGE_KEY_KEYBOARD_RETURN || key == HID_USAGE_KEY_KEYBOARD_RETURN_ENTER) {
uint8_t digits[PASSKEY_DIGITS];
uint32_t count = ring_buf_get(&passkey_entries, digits, PASSKEY_DIGITS);

if (passkey_digit == PASSKEY_DIGITS) {
uint32_t passkey = 0;
for (int i = 0; i < PASSKEY_DIGITS; i++) {
passkey = (passkey * 10) + passkey_entries[i];
for (int i = 0; i < count; i++) {
passkey = (passkey * 10) + digits[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 ZMK_EV_EVENT_HANDLED;
}

uint8_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;
}

if (ring_buf_space_get(&passkey_entries) <= 0) {
uint8_t discard_val;
ring_buf_get(&passkey_entries, &discard_val, 1);
}
ring_buf_put(&passkey_entries, &val, 1);
LOG_DBG("value entered: %d, digits collected so far: %d", val,
ring_buf_size_get(&passkey_entries));

return ZMK_EV_EVENT_HANDLED;
}
Expand Down
7 changes: 4 additions & 3 deletions docs/docs/config/bluetooth.md
Expand Up @@ -9,6 +9,7 @@ See [Configuration Overview](index.md) for instructions on how to change these s

## Kconfig

| Option | Type | Description | Default |
| ------------------------------------- | ---- | ----------------------------------------------------------------------------------------------------------------------- | ------- |
| `CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION` | bool | Low level setting for GATT subscriptions. Set to `n` to work around an annoying Windows bug with battery notifications. | y |
| Option | Type | Description | Default |
| ------------------------------------- | ---- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `CONFIG_ZMK_BLE_PASSKEY_ENTRY` | bool | Enable passkey entry during pairing for enhanced security. (Note: After enabling this, you will need to re-pair all previously paired hosts) | n |
| `CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION` | bool | Low level setting for GATT subscriptions. Set to `n` to work around an annoying Windows bug with battery notifications. | y |