feat(endpoints): update on BLE profile change

Added zmk_ble_active_profile_is_connected() to allow code outside ble.c to check
the status of the active profile, and changed the ble_active_profile_changed
event to also notify when the active profile connects or disconnects.

Changed endpoint selection to to also update when the active profile changes,
connects, or disconnects.
This commit is contained in:
Joel Spadin 2020-10-24 13:39:02 -05:00
parent 8f666cecc9
commit b538e60532
3 changed files with 42 additions and 9 deletions

View file

@ -15,6 +15,7 @@ int zmk_ble_prof_prev();
int zmk_ble_prof_select(u8_t index); int zmk_ble_prof_select(u8_t index);
bt_addr_le_t *zmk_ble_active_profile_addr(); bt_addr_le_t *zmk_ble_active_profile_addr();
bool zmk_ble_active_profile_is_connected();
char *zmk_ble_active_profile_name(); char *zmk_ble_active_profile_name();
int zmk_ble_unpair_all(); int zmk_ble_unpair_all();

View file

@ -94,6 +94,12 @@ static void raise_profile_changed_event() {
ZMK_EVENT_RAISE(ev); ZMK_EVENT_RAISE(ev);
} }
static void raise_profile_changed_event_callback(struct k_work *work) {
raise_profile_changed_event();
}
K_WORK_DEFINE(raise_profile_changed_event_work, raise_profile_changed_event_callback);
static bool active_profile_is_open() { static bool active_profile_is_open() {
return !bt_addr_le_cmp(&profiles[active_profile].peer, BT_ADDR_LE_ANY); return !bt_addr_le_cmp(&profiles[active_profile].peer, BT_ADDR_LE_ANY);
} }
@ -111,7 +117,7 @@ void set_profile_address(u8_t index, const bt_addr_le_t *addr) {
raise_profile_changed_event(); raise_profile_changed_event();
} }
bool active_profile_is_connected() { bool zmk_ble_active_profile_is_connected() {
struct bt_conn *conn; struct bt_conn *conn;
bt_addr_le_t *addr = zmk_ble_active_profile_addr(); bt_addr_le_t *addr = zmk_ble_active_profile_addr();
if (!bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { if (!bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) {
@ -163,9 +169,9 @@ int update_advertising() {
struct bt_conn *conn; struct bt_conn *conn;
enum advertising_type desired_adv = ZMK_ADV_NONE; enum advertising_type desired_adv = ZMK_ADV_NONE;
if (active_profile_is_open() || !active_profile_is_connected()) { if (active_profile_is_open() || !zmk_ble_active_profile_is_connected()) {
desired_adv = ZMK_ADV_CONN; desired_adv = ZMK_ADV_CONN;
} else if (!active_profile_is_connected()) { } else if (!zmk_ble_active_profile_is_connected()) {
desired_adv = ZMK_ADV_CONN; desired_adv = ZMK_ADV_CONN;
// Need to fix directed advertising for privacy centrals. See // Need to fix directed advertising for privacy centrals. See
// https://github.com/zephyrproject-rtos/zephyr/pull/14984 char // https://github.com/zephyrproject-rtos/zephyr/pull/14984 char
@ -327,6 +333,10 @@ static int ble_profiles_handle_set(const char *name, size_t len, settings_read_c
struct settings_handler profiles_handler = {.name = "ble", .h_set = ble_profiles_handle_set}; struct settings_handler profiles_handler = {.name = "ble", .h_set = ble_profiles_handle_set};
#endif /* IS_ENABLED(CONFIG_SETTINGS) */ #endif /* IS_ENABLED(CONFIG_SETTINGS) */
static bool is_conn_active_profile(const struct bt_conn *conn) {
return bt_addr_le_cmp(bt_conn_get_dst(conn), &profiles[active_profile].peer) == 0;
}
static void connected(struct bt_conn *conn, u8_t err) { static void connected(struct bt_conn *conn, u8_t err) {
char addr[BT_ADDR_LE_STR_LEN]; char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
@ -352,6 +362,11 @@ static void connected(struct bt_conn *conn, u8_t err) {
} }
update_advertising(); update_advertising();
if (is_conn_active_profile(conn)) {
LOG_DBG("Active profile connected");
raise_profile_changed_event();
}
} }
static void disconnected(struct bt_conn *conn, u8_t reason) { static void disconnected(struct bt_conn *conn, u8_t reason) {
@ -364,6 +379,11 @@ static void disconnected(struct bt_conn *conn, u8_t reason) {
// We need to do this in a work callback, otherwise the advertising update will still see the // We need to do this in a work callback, otherwise the advertising update will still see the
// connection for a profile as active, and not start advertising yet. // connection for a profile as active, and not start advertising yet.
k_work_submit(&update_advertising_work); k_work_submit(&update_advertising_work);
if (is_conn_active_profile(conn)) {
LOG_DBG("Active profile disconnected");
k_work_submit(&raise_profile_changed_event_work);
}
} }
static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) { static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) {

View file

@ -4,11 +4,13 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
#include <zmk/ble.h>
#include <zmk/endpoints.h> #include <zmk/endpoints.h>
#include <zmk/hid.h> #include <zmk/hid.h>
#include <zmk/usb.h> #include <zmk/usb.h>
#include <zmk/hog.h> #include <zmk/hog.h>
#include <zmk/event-manager.h> #include <zmk/event-manager.h>
#include <zmk/events/ble-active-profile-changed.h>
#include <zmk/events/usb-conn-state-changed.h> #include <zmk/events/usb-conn-state-changed.h>
#include <logging/log.h> #include <logging/log.h>
@ -19,8 +21,9 @@ enum endpoint {
ENDPOINT_BLE, ENDPOINT_BLE,
}; };
static enum endpoint current_endpoint = #define DEFAULT_ENDPOINT COND_CODE_1(IS_ENABLED(CONFIG_ZMK_BLE), (ENDPOINT_BLE), (ENDPOINT_USB))
COND_CODE_1(IS_ENABLED(CONFIG_ZMK_BLE), (ENDPOINT_BLE), (ENDPOINT_USB));
static enum endpoint current_endpoint = DEFAULT_ENDPOINT;
static int send_keypad_report() { static int send_keypad_report() {
struct zmk_hid_keypad_report *keypad_report = zmk_hid_get_keypad_report(); struct zmk_hid_keypad_report *keypad_report = zmk_hid_get_keypad_report();
@ -115,15 +118,22 @@ static bool is_ble_ready() {
static enum endpoint get_selected_endpoint() { static enum endpoint get_selected_endpoint() {
if (is_ble_ready()) { if (is_ble_ready()) {
if (is_usb_ready()) { if (is_usb_ready()) {
LOG_DBG("Both endpoints ready. Selecting USB"); LOG_DBG("Both endpoints are ready.");
// TODO: add user setting to control this // TODO: add user setting to control this
return ENDPOINT_USB; return ENDPOINT_USB;
} }
LOG_DBG("Only BLE is ready.");
return ENDPOINT_BLE; return ENDPOINT_BLE;
} }
if (is_usb_ready()) {
LOG_DBG("Only USB is ready.");
return ENDPOINT_USB; return ENDPOINT_USB;
}
LOG_DBG("No endpoints are ready.");
return DEFAULT_ENDPOINT;
} }
static void disconnect_current_endpoint() { static void disconnect_current_endpoint() {
@ -149,7 +159,9 @@ static int endpoint_listener(const struct zmk_event_header *eh) {
} }
ZMK_LISTENER(endpoint_listener, endpoint_listener); ZMK_LISTENER(endpoint_listener, endpoint_listener);
#if IS_ENABLED(CONFIG_USB) #if IS_ENABLED(CONFIG_ZMK_USB)
ZMK_SUBSCRIPTION(endpoint_listener, usb_conn_state_changed); ZMK_SUBSCRIPTION(endpoint_listener, usb_conn_state_changed);
#endif #endif
// TODO: add BLE state subscription #if IS_ENABLED(CONFIG_ZMK_BLE)
ZMK_SUBSCRIPTION(endpoint_listener, ble_active_profile_changed);
#endif