@ -25,49 +25,30 @@
# endif
# endif
# include <logging/log.h>
# include <logging/log.h>
LOG_MODULE_DECLARE ( zmk , CONFIG_ZMK_LOG_LEVEL ) ;
LOG_MODULE_DECLARE ( zmk , CONFIG_ZMK_LOG_LEVEL ) ;
# include <zmk/ble.h>
# include <zmk/keys.h>
# include <zmk/keys.h>
# include <zmk/split/bluetooth/uuid.h>
# include <zmk/split/bluetooth/uuid.h>
# include <zmk/event-manager.h>
# include <zmk/events/ble-active-profile-changed.h>
static struct bt_conn * auth_passkey_entry_conn ;
static struct bt_conn * auth_passkey_entry_conn ;
static u8_t passkey_entries [ 6 ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
static u8_t passkey_entries [ 6 ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
static u8_t passkey_digit = 0 ;
static u8_t passkey_digit = 0 ;
# define ZMK_BT_LE_ADV_PARAM_INIT(_id, _options, _int_min, _int_max, _peer) \
{ \
. id = _id , \
. sid = 0 , \
. secondary_max_skip = 0 , \
. options = ( _options ) , \
. interval_min = ( _int_min ) , \
. interval_max = ( _int_max ) , \
. peer = ( _peer ) , \
}
# define ZMK_BT_LE_ADV_PARAM(_id, _options, _int_min, _int_max, _peer) \
( ( struct bt_le_adv_param [ ] ) { \
ZMK_BT_LE_ADV_PARAM_INIT ( _id , _options , _int_min , _int_max , _peer ) \
} )
# if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
# if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
# define ZMK_ADV_PARAMS(_id) ZMK_BT_LE_ADV_PARAM(_id, \
# define PROFILE_COUNT (CONFIG_BT_MAX_PAIRED - 1)
BT_LE_ADV_OPT_CONNECTABLE | \
BT_LE_ADV_OPT_ONE_TIME | \
BT_LE_ADV_OPT_USE_NAME , \
BT_GAP_ADV_FAST_INT_MIN_2 , \
BT_GAP_ADV_FAST_INT_MAX_2 , NULL )
# else
# else
# define ZMK_ADV_PARAMS(_id) ZMK_BT_LE_ADV_PARAM(_id, \
# define PROFILE_COUNT CONFIG_BT_MAX_PAIRED
BT_LE_ADV_OPT_CONNECTABLE | \
BT_LE_ADV_OPT_USE_NAME , \
BT_GAP_ADV_FAST_INT_MIN_2 , \
BT_GAP_ADV_FAST_INT_MAX_2 , NULL )
# endif
# endif
static struct zmk_ble_profile profiles [ PROFILE_COUNT ] ;
static u8_t active_profile ;
static const struct bt_data zmk_ble_ad [ ] = {
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_FLAGS , ( BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR ) ) ,
BT_DATA_BYTES ( BT_DATA_UUID16_SOME ,
BT_DATA_BYTES ( BT_DATA_UUID16_SOME ,
@ -88,6 +69,33 @@ static bt_addr_le_t peripheral_addr;
# endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
# endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
static void raise_profile_changed_event ( )
{
struct ble_active_profile_changed * ev = new_ble_active_profile_changed ( ) ;
ev - > index = active_profile ;
ev - > profile = & profiles [ active_profile ] ;
ZMK_EVENT_RAISE ( ev ) ;
}
static bool active_profile_is_open ( )
{
return ! bt_addr_le_cmp ( & profiles [ active_profile ] . peer , BT_ADDR_LE_ANY ) ;
}
void set_profile_address ( u8_t index , const bt_addr_le_t * addr )
{
char setting_name [ 15 ] ;
char addr_str [ BT_ADDR_LE_STR_LEN ] ;
bt_addr_le_to_str ( addr , addr_str , sizeof ( addr_str ) ) ;
memcpy ( & profiles [ index ] . peer , addr , sizeof ( bt_addr_le_t ) ) ;
sprintf ( setting_name , " ble/profiles/%d " , index ) ;
LOG_DBG ( " Setting profile addr for %s to %s " , log_strdup ( setting_name ) , log_strdup ( addr_str ) ) ;
settings_save_one ( setting_name , & profiles [ index ] , sizeof ( struct zmk_ble_profile ) ) ;
raise_profile_changed_event ( ) ;
}
int zmk_ble_adv_pause ( )
int zmk_ble_adv_pause ( )
{
{
@ -102,10 +110,12 @@ int zmk_ble_adv_pause()
int zmk_ble_adv_resume ( )
int zmk_ble_adv_resume ( )
{
{
struct bt_le_adv_param * adv_params = ZMK_ADV_PARAMS ( BT_ID_DEFAULT ) ;
LOG_DBG ( " active_profile %d, directed? %s " , active_profile , active_profile_is_open ( ) ? " no " : " yes " ) ;
LOG_DBG ( " " ) ;
int err = bt_le_adv_start (
int err = bt_le_adv_start ( adv_params , zmk_ble_ad , ARRAY_SIZE ( zmk_ble_ad ) , NULL , 0 ) ;
BT_LE_ADV_CONN_NAME ,
zmk_ble_ad , ARRAY_SIZE ( zmk_ble_ad ) ,
NULL , 0 ) ;
if ( err )
if ( err )
{
{
LOG_ERR ( " Advertising failed to start (err %d) " , err ) ;
LOG_ERR ( " Advertising failed to start (err %d) " , err ) ;
@ -115,44 +125,54 @@ int zmk_ble_adv_resume()
return 0 ;
return 0 ;
} ;
} ;
static void disconnect_host_connection ( struct bt_conn * conn , void * arg )
int zmk_ble_clear_bonds ( )
{
{
struct bt_conn_info info ;
LOG_DBG ( " " ) ;
bt_conn_get_info ( conn , & info ) ;
if ( bt_addr_le_cmp ( & profiles [ active_profile ] . peer , BT_ADDR_LE_ANY ) ) {
if ( info . role ! = BT_CONN_ROLE_SLAVE ) {
LOG_DBG ( " Unpairing! " ) ;
return ;
bt_unpair ( BT_ID_DEFAULT , & profiles [ active_profile ] . peer ) ;
set_profile_address ( active_profile , BT_ADDR_LE_ANY ) ;
}
}
bt_conn_disconnect ( conn , BT_HCI_ERR_LOCALHOST_TERM_CONN ) ;
return 0 ;
} ;
} ;
int zmk_ble_prof_select ( u8_t index )
static void unpair_non_peripheral_bonds ( const struct bt_bond_info * info , void * user_data ) {
{
char addr [ BT_ADDR_LE_STR_LEN ] ;
LOG_DBG ( " profile %d " , index ) ;
bt_addr_le_to_str ( & info - > addr , addr , sizeof ( addr ) ) ;
if ( active_profile = = index ) {
return 0 ;
# if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
if ( ! bt_addr_le_cmp ( & info - > addr , & peripheral_addr ) ) {
LOG_DBG ( " Skipping unpairing peripheral %s " , log_strdup ( addr ) ) ;
return ;
}
}
# endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
LOG_DBG ( " Unpairing %s " , log_strdup ( addr ) ) ;
active_profile = index ;
bt_unpair ( BT_ID_DEFAULT , & info - > addr ) ;
return settings_save_one ( " ble/active_profile " , & active_profile , sizeof ( active_profile ) ) ;
}
int zmk_ble_clear_bonds ( )
raise_profile_changed_event ( ) ;
} ;
int zmk_ble_prof_next ( )
{
{
LOG_DBG ( " " ) ;
LOG_DBG ( " " ) ;
return zmk_ble_prof_select ( ( active_profile + 1 ) % PROFILE_COUNT ) ;
bt_conn_foreach ( BT_ID_DEFAULT , disconnect_host_connection , NULL ) ;
} ;
bt_foreach_bond ( BT_ID_DEFAULT , unpair_non_peripheral_bonds , NULL ) ;
return 0 ;
int zmk_ble_prof_prev ( )
{
LOG_DBG ( " " ) ;
return zmk_ble_prof_select ( ( active_profile + PROFILE_COUNT - 1 ) % PROFILE_COUNT ) ;
} ;
} ;
bt_addr_le_t * zmk_ble_active_profile_addr ( )
{
return & profiles [ active_profile ] . peer ;
}
char * zmk_ble_active_profile_name ( )
{
return profiles [ active_profile ] . name ;
}
# if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
# if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
void zmk_ble_set_peripheral_addr ( bt_addr_le_t * addr )
void zmk_ble_set_peripheral_addr ( bt_addr_le_t * addr )
@ -171,8 +191,47 @@ static int ble_profiles_handle_set(const char *name, size_t len, settings_read_c
LOG_DBG ( " Setting BLE value %s " , log_strdup ( name ) ) ;
LOG_DBG ( " Setting BLE value %s " , log_strdup ( name ) ) ;
if ( settings_name_steq ( name , " profiles " , & next ) & & next ) {
char * endptr ;
u8_t idx = strtoul ( next , & endptr , 10 ) ;
if ( * endptr ! = ' \0 ' ) {
LOG_WRN ( " Invalid profile index: %s " , log_strdup ( next ) ) ;
return - EINVAL ;
}
if ( len ! = sizeof ( struct zmk_ble_profile ) ) {
LOG_ERR ( " Invalid profile size (got %d expected %d) " , len , sizeof ( struct zmk_ble_profile ) ) ;
return - EINVAL ;
}
if ( idx > = PROFILE_COUNT ) {
LOG_WRN ( " Profile address for index %d is larger than max of %d " , idx , PROFILE_COUNT ) ;
return - EINVAL ;
}
int err = read_cb ( cb_arg , & profiles [ idx ] , sizeof ( struct zmk_ble_profile ) ) ;
if ( err < = 0 ) {
LOG_ERR ( " Failed to handle profile address from settings (err %d) " , err ) ;
return err ;
}
char addr_str [ BT_ADDR_LE_STR_LEN ] ;
bt_addr_le_to_str ( & profiles [ idx ] . peer , addr_str , sizeof ( addr_str ) ) ;
LOG_DBG ( " Loaded %s address for profile %d " , log_strdup ( addr_str ) , idx ) ;
} else if ( settings_name_steq ( name , " active_profile " , & next ) & & ! next ) {
if ( len ! = sizeof ( active_profile ) ) {
return - EINVAL ;
}
int err = read_cb ( cb_arg , & active_profile , sizeof ( active_profile ) ) ;
if ( err < = 0 ) {
LOG_ERR ( " Failed to handle active profile from settings (err %d) " , err ) ;
return err ;
}
}
# if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
# if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
if ( settings_name_steq ( name , " peripheral_address " , & next ) & & ! next ) {
else if ( settings_name_steq ( name , " peripheral_address " , & next ) & & ! next ) {
if ( len ! = sizeof ( bt_addr_le_t ) ) {
if ( len ! = sizeof ( bt_addr_le_t ) ) {
return - EINVAL ;
return - EINVAL ;
}
}
@ -197,7 +256,6 @@ struct settings_handler profiles_handler = {
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 ) ) ;
if ( err )
if ( err )
@ -229,11 +287,11 @@ static void disconnected(struct bt_conn *conn, u8_t reason)
LOG_DBG ( " Disconnected from %s (reason 0x%02x) " , log_strdup ( addr ) , reason ) ;
LOG_DBG ( " Disconnected from %s (reason 0x%02x) " , log_strdup ( addr ) , reason ) ;
# if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
# if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
if ( bt_addr_le_cmp ( & peripheral_addr , BT_ADDR_LE_ANY ) & & bt_addr_le_cmp ( & peripheral_addr , bt_conn_get_dst ( conn ) ) ) {
// if (bt_addr_le_cmp(&peripheral_addr, BT_ADDR_LE_ANY) && bt_addr_le_cmp(&peripheral_addr, bt_conn_get_dst(conn))) {
zmk_ble_adv_resume ( ) ;
// zmk_ble_adv_resume();
}
// }
# else
# else
zmk_ble_adv_resume ( ) ;
// zmk_ble_adv_resume();
# endif
# endif
}
}
@ -301,7 +359,52 @@ static void auth_cancel(struct bt_conn *conn)
LOG_DBG ( " Pairing cancelled: %s " , log_strdup ( addr ) ) ;
LOG_DBG ( " Pairing cancelled: %s " , log_strdup ( addr ) ) ;
}
}
# if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_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 ;
bt_conn_get_info ( conn , & info ) ;
LOG_DBG ( " role %d, open? %s " , info . role , active_profile_is_open ( ) ? " yes " : " no " ) ;
if ( info . role ! = BT_CONN_ROLE_SLAVE & & ! active_profile_is_open ( ) ) {
LOG_WRN ( " Rejecting pairing request to taken profile %d " , active_profile ) ;
return BT_SECURITY_ERR_PAIR_NOT_ALLOWED ;
}
return BT_SECURITY_ERR_SUCCESS ;
} ;
# endif /* !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) */
static void auth_pairing_complete ( struct bt_conn * conn , bool bonded )
{
struct bt_conn_info info ;
char addr [ BT_ADDR_LE_STR_LEN ] ;
const bt_addr_le_t * dst = bt_conn_get_dst ( conn ) ;
bt_addr_le_to_str ( dst , addr , sizeof ( addr ) ) ;
bt_conn_get_info ( conn , & info ) ;
if ( info . role ! = BT_CONN_ROLE_SLAVE ) {
LOG_DBG ( " SKIPPING FOR ROLE %d " , info . role ) ;
return ;
}
# if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
if ( ! 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_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) */
set_profile_address ( active_profile , dst ) ;
} ;
static struct bt_conn_auth_cb zmk_ble_auth_cb_display = {
static struct bt_conn_auth_cb zmk_ble_auth_cb_display = {
# if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
. pairing_accept = auth_pairing_accept ,
# endif /* !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) */
. pairing_complete = auth_pairing_complete ,
// .passkey_display = auth_passkey_display,
// .passkey_display = auth_passkey_display,
# ifdef CONFIG_ZMK_BLE_PASSKEY_ENTRY
# ifdef CONFIG_ZMK_BLE_PASSKEY_ENTRY
@ -348,11 +451,20 @@ static int zmk_ble_init(struct device *_arg)
# if IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START)
# if IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START)
LOG_WRN ( " Clearing all existing BLE bond information from the keyboard " ) ;
LOG_WRN ( " Clearing all existing BLE bond information from the keyboard " ) ;
settings_delete ( " bt/name " ) ;
for ( int i = 0 ; i < 10 ; i + + ) {
for ( int i = 0 ; i < 10 ; i + + ) {
bt_unpair ( i , NULL ) ;
bt_unpair ( i , NULL ) ;
}
}
for ( int i = 0 ; i < PROFILE_COUNT ; i + + ) {
char setting_name [ 15 ] ;
sprintf ( setting_name , " ble/profiles/%d " , i ) ;
err = settings_delete ( setting_name ) ;
if ( err ) {
LOG_ERR ( " Failed to delete setting: %d " , err ) ;
}
}
# endif
# endif
bt_conn_cb_register ( & conn_callbacks ) ;
bt_conn_cb_register ( & conn_callbacks ) ;