refactor(split): Seperate peripheral BLE handling.

* Move foundational BLE code for split
  peripherals to a dedicated file to avoid
  tons of conditionals and awkward code.
This commit is contained in:
Peter Johanson 2022-04-24 21:22:20 +00:00 committed by Pete Johanson
parent 25f89ee6ab
commit 0a40f922b5
3 changed files with 134 additions and 55 deletions

View File

@ -63,27 +63,34 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
target_sources(app PRIVATE src/combo.c)
target_sources(app PRIVATE src/behavior_queue.c)
target_sources(app PRIVATE src/conditional_layer.c)
target_sources(app PRIVATE src/endpoints.c)
target_sources(app PRIVATE src/hid_listener.c)
target_sources(app PRIVATE src/keymap.c)
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/behaviors/behavior_bt.c)
if (CONFIG_ZMK_BLE)
target_sources(app PRIVATE src/ble.c)
target_sources(app PRIVATE src/hog.c)
endif()
endif()
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/behaviors/behavior_rgb_underglow.c)
target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/behaviors/behavior_backlight.c)
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/behaviors/behavior_bt.c)
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble.c)
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/battery.c)
if (CONFIG_ZMK_SPLIT_BLE AND (NOT CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL))
target_sources(app PRIVATE src/split_listener.c)
target_sources(app PRIVATE src/split/bluetooth/service.c)
target_sources(app PRIVATE src/split_listener.c)
target_sources(app PRIVATE src/split/bluetooth/service.c)
target_sources(app PRIVATE src/split/bluetooth/peripheral.c)
endif()
if (CONFIG_ZMK_SPLIT_BLE AND CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
target_sources(app PRIVATE src/split/bluetooth/central.c)
target_sources(app PRIVATE src/split/bluetooth/central.c)
endif()
target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/usb.c)
target_sources_ifdef(CONFIG_ZMK_USB app PRIVATE src/usb_hid.c)
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/hog.c)
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c)
target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/backlight.c)
target_sources(app PRIVATE src/endpoints.c)
target_sources(app PRIVATE src/hid_listener.c)
target_sources(app PRIVATE src/main.c)
add_subdirectory(src/display/)

View File

@ -36,14 +36,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/event_manager.h>
#include <zmk/events/ble_active_profile_changed.h>
#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
#if IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY)
#include <zmk/events/keycode_state_changed.h>
#define PASSKEY_DIGITS 6
@ -52,7 +45,7 @@ static struct bt_conn *auth_passkey_entry_conn;
static uint8_t passkey_entries[PASSKEY_DIGITS] = {};
static uint8_t passkey_digit = 0;
#endif
#endif /* IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) */
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
#define PROFILE_COUNT (CONFIG_BT_MAX_PAIRED - 1)
@ -81,20 +74,12 @@ static uint8_t active_profile;
BUILD_ASSERT(DEVICE_NAME_LEN <= 16, "ERROR: BLE device name is too long. Max length: 16");
static const struct bt_data zmk_ble_ad[] = {
#if IS_HOST_PERIPHERAL
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
BT_DATA_BYTES(BT_DATA_GAP_APPEARANCE, 0xC1, 0x03),
#endif
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA_BYTES(BT_DATA_UUID16_SOME,
#if IS_HOST_PERIPHERAL
0x12, 0x18, /* HID Service */
#endif
0x0f, 0x18 /* Battery Service */
BT_DATA_BYTES(BT_DATA_UUID16_SOME, 0x12, 0x18, /* HID Service */
0x0f, 0x18 /* Battery Service */
),
#if IS_SPLIT_PERIPHERAL
BT_DATA_BYTES(BT_DATA_UUID128_ALL, ZMK_SPLIT_BT_SERVICE_UUID)
#endif
};
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
@ -473,7 +458,7 @@ static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey) {
}
*/
#if DO_PASSKEY_ENTRY
#if IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY)
static void auth_passkey_entry(struct bt_conn *conn) {
char addr[BT_ADDR_LE_STR_LEN];
@ -492,7 +477,7 @@ 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 IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY)
if (auth_passkey_entry_conn) {
bt_conn_unref(auth_passkey_entry_conn);
auth_passkey_entry_conn = NULL;
@ -504,7 +489,6 @@ static void auth_cancel(struct bt_conn *conn) {
LOG_DBG("Pairing cancelled: %s", log_strdup(addr));
}
#if IS_HOST_PERIPHERAL
static enum bt_security_err auth_pairing_accept(struct bt_conn *conn,
const struct bt_conn_pairing_feat *const feat) {
struct bt_conn_info info;
@ -518,7 +502,6 @@ static enum bt_security_err auth_pairing_accept(struct bt_conn *conn,
return BT_SECURITY_ERR_SUCCESS;
};
#endif /* IS_HOST_PERIPHERAL */
static void auth_pairing_complete(struct bt_conn *conn, bool bonded) {
struct bt_conn_info info;
@ -533,26 +516,22 @@ static void auth_pairing_complete(struct bt_conn *conn, bool bonded) {
return;
}
#if IS_HOST_PERIPHERAL
if (!zmk_ble_active_profile_is_open()) {
LOG_ERR("Pairing completed but current profile is not open: %s", log_strdup(addr));
bt_unpair(BT_ID_DEFAULT, dst);
return;
}
#endif /* IS_HOST_PERIPHERAL */
set_profile_address(active_profile, dst);
update_advertising();
};
static struct bt_conn_auth_cb zmk_ble_auth_cb_display = {
#if IS_HOST_PERIPHERAL
.pairing_accept = auth_pairing_accept,
#endif /* IS_HOST_PERIPHERAL */
.pairing_complete = auth_pairing_complete,
// .passkey_display = auth_passkey_display,
#if DO_PASSKEY_ENTRY
#if IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY)
.passkey_entry = auth_passkey_entry,
#endif
.cancel = auth_cancel,
@ -595,9 +574,7 @@ static int zmk_ble_init(const struct device *_arg) {
#if IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START)
LOG_WRN("Clearing all existing BLE bond information from the keyboard");
for (int i = 0; i < 10; i++) {
bt_unpair(i, NULL);
}
bt_unpair(BT_ID_DEFAULT, NULL);
for (int i = 0; i < ZMK_BLE_PROFILE_COUNT; i++) {
char setting_name[15];
@ -618,21 +595,7 @@ static int zmk_ble_init(const struct device *_arg) {
return 0;
}
int zmk_ble_unpair_all() {
int resp = 0;
for (int i = BT_ID_DEFAULT; i < CONFIG_BT_ID_MAX; i++) {
int err = bt_unpair(BT_ID_DEFAULT, NULL);
if (err) {
resp = err;
LOG_ERR("Failed to unpair devices (err %d)", err);
}
}
return resp;
};
#if DO_PASSKEY_ENTRY
#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) {
@ -705,6 +668,6 @@ static int zmk_ble_listener(const zmk_event_t *eh) {
ZMK_LISTENER(zmk_ble, zmk_ble_listener);
ZMK_SUBSCRIPTION(zmk_ble, zmk_keycode_state_changed);
#endif /* DO_PASSKEY_ENTRY */
#endif /* IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) */
SYS_INIT(zmk_ble_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <device.h>
#include <init.h>
#include <errno.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <settings/settings.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/conn.h>
#include <bluetooth/hci.h>
#include <bluetooth/uuid.h>
#include <bluetooth/gatt.h>
#include <bluetooth/hci_err.h>
#if IS_ENABLED(CONFIG_SETTINGS)
#include <settings/settings.h>
#endif
#include <logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/ble.h>
#include <zmk/split/bluetooth/uuid.h>
static const struct bt_data zmk_ble_ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA_BYTES(BT_DATA_UUID16_SOME, 0x0f, 0x18 /* Battery Service */
),
BT_DATA_BYTES(BT_DATA_UUID128_ALL, ZMK_SPLIT_BT_SERVICE_UUID)};
static int start_advertising() {
return bt_le_adv_start(BT_LE_ADV_CONN, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0);
};
static void disconnected(struct bt_conn *conn, uint8_t reason) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_DBG("Disconnected from %s (reason 0x%02x)", log_strdup(addr), reason);
}
static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
if (!err) {
LOG_DBG("Security changed: %s level %u", log_strdup(addr), level);
} else {
LOG_ERR("Security failed: %s level %u err %d", log_strdup(addr), level, err);
}
}
static void le_param_updated(struct bt_conn *conn, uint16_t interval, uint16_t latency,
uint16_t timeout) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_DBG("%s: interval %d latency %d timeout %d", log_strdup(addr), interval, latency, timeout);
}
static struct bt_conn_cb conn_callbacks = {
.disconnected = disconnected,
.security_changed = security_changed,
.le_param_updated = le_param_updated,
};
static int zmk_peripheral_ble_init(const struct device *_arg) {
int err = bt_enable(NULL);
if (err) {
LOG_ERR("BLUETOOTH FAILED (%d)", err);
return err;
}
#if IS_ENABLED(CONFIG_SETTINGS)
settings_subsys_init();
settings_load_subtree("ble");
settings_load_subtree("bt");
#endif
#if IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START)
LOG_WRN("Clearing all existing BLE bond information from the keyboard");
bt_unpair(BT_ID_DEFAULT, NULL);
#endif
bt_conn_cb_register(&conn_callbacks);
start_advertising();
return 0;
}
SYS_INIT(zmk_peripheral_ble_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);