diff --git a/applications/main/bad_kb/bad_kb_app.c b/applications/main/bad_kb/bad_kb_app.c index 2f5ee75ff..f7c9fcd41 100644 --- a/applications/main/bad_kb/bad_kb_app.c +++ b/applications/main/bad_kb/bad_kb_app.c @@ -107,10 +107,12 @@ BadKbApp* bad_kb_app_alloc(char* arg) { Bt* bt = furi_record_open(RECORD_BT); app->bt = bt; app->is_bt = XTREME_SETTINGS()->bad_bt; + app->bonding = BondingForgetDevices; const char* adv_name = furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard); memcpy(app->name, adv_name, BAD_KB_ADV_NAME_MAX_LEN); memcpy(app->bt_old_config.name, adv_name, BAD_KB_ADV_NAME_MAX_LEN); + // need to be done before bt init (where mac address get modified if bounding is activated) const uint8_t* mac_addr = furi_hal_bt_get_profile_mac_addr(FuriHalBtProfileHidKeyboard); memcpy(app->mac, mac_addr, BAD_KB_MAC_ADDRESS_LEN); memcpy(app->bt_old_config.mac, mac_addr, BAD_KB_MAC_ADDRESS_LEN); diff --git a/applications/main/bad_kb/bad_kb_app_i.h b/applications/main/bad_kb/bad_kb_app_i.h index b16eb159d..1263ab49c 100644 --- a/applications/main/bad_kb/bad_kb_app_i.h +++ b/applications/main/bad_kb/bad_kb_app_i.h @@ -18,11 +18,16 @@ #define BAD_KB_APP_BASE_FOLDER ANY_PATH("badkb") #define BAD_KB_APP_PATH_LAYOUT_FOLDER BAD_KB_APP_BASE_FOLDER "/assets/layouts" +#define BAD_KB_APP_PATH_BOUND_KEYS_FOLDER EXT_PATH("badkb/.bt_keys") +#define BAD_KB_APP_PATH_BOUND_KEYS_FILE BAD_KB_APP_PATH_BOUND_KEYS_FOLDER "/.devices.keys" #define BAD_KB_APP_SCRIPT_EXTENSION ".txt" #define BAD_KB_APP_LAYOUT_EXTENSION ".kl" -#define BAD_KB_MAC_ADDRESS_LEN 6 // need replace with MAC size maccro -#define BAD_KB_ADV_NAME_MAX_LEN 18 +#define BAD_KB_MAC_ADDRESS_LEN 6 // need replace with MAC size maccro +#define BAD_KB_ADV_NAME_MAX_LEN 18 + +// this is the MAC address used when we do not forget paired device (BOUND STATE) +#define BAD_KB_BOUND_MAC_ADDRESS { 0x41, 0x4a, 0xef, 0xbe, 0xad, 0xde }; typedef enum { BadKbAppErrorNoFiles, @@ -35,13 +40,14 @@ typedef enum BadKbCustomEvent { BadKbCustomEventErrorBack } BadKbCustomEvent; + +#define BondingForgetDevices false +#define BondingRememberDevices true + typedef struct { + //uint8_t bounded_mac[BAD_KB_MAC_ADDRESS_LEN]; uint8_t mac[BAD_KB_MAC_ADDRESS_LEN]; char name[BAD_KB_ADV_NAME_MAX_LEN + 1]; - - // number of bt keys before starting the app (all keys added in - // the bt keys file then will be removed) - uint16_t n_keys; } BadKbBtConfig; struct BadKbApp { @@ -59,6 +65,7 @@ struct BadKbApp { ByteInput* byte_input; uint8_t mac[BAD_KB_MAC_ADDRESS_LEN]; char name[BAD_KB_ADV_NAME_MAX_LEN + 1]; + bool bonding; // weither we remember paired devices or not BadKbBtConfig bt_old_config; BadKbAppError error; diff --git a/applications/main/bad_kb/bad_kb_script.c b/applications/main/bad_kb/bad_kb_script.c index d6cb6fae6..469d4169a 100644 --- a/applications/main/bad_kb/bad_kb_script.c +++ b/applications/main/bad_kb/bad_kb_script.c @@ -169,19 +169,19 @@ static const uint8_t numpad_keys[10] = { uint8_t bt_timeout = 0; static LevelRssiRange bt_remote_rssi_range(Bt* bt) { - BtRssi rssi_data = {0}; + uint8_t rssi; - if(!bt_remote_rssi(bt, &rssi_data)) return LevelRssiError; + if(!bt_remote_rssi(bt, &rssi)) return LevelRssiError; - if(rssi_data.rssi <= 39) + if(rssi <= 39) return LevelRssi39_0; - else if(rssi_data.rssi <= 59) + else if(rssi <= 59) return LevelRssi59_40; - else if(rssi_data.rssi <= 79) + else if(rssi <= 79) return LevelRssi79_60; - else if(rssi_data.rssi <= 99) + else if(rssi <= 99) return LevelRssi99_80; - else if(rssi_data.rssi <= 122) + else if(rssi <= 122) return LevelRssi122_100; return LevelRssiError; @@ -629,6 +629,23 @@ void bad_kb_config_switch_mode(BadKbApp* app) { } } +void bad_kb_config_switch_bonding_mode(BadKbApp *app) { + if (app->bonding) { + // set bouding mac + uint8_t mac[6] = BAD_KB_BOUND_MAC_ADDRESS; + furi_hal_bt_set_profile_pairing_method(FuriHalBtProfileHidKeyboard, GapPairingPinCodeVerifyYesNo); + bt_set_profile_mac_address(app->bt, mac); // this also restart bt + // enable keys storage + bt_enable_peer_key_update(app->bt); + } else { + // set back user defined mac address + furi_hal_bt_set_profile_pairing_method(FuriHalBtProfileHidKeyboard, GapPairingNone); + bt_set_profile_mac_address(app->bt, app->mac); + // disable key storage + bt_disable_peer_key_update(app->bt); + } +} + void bad_kb_connection_init(BadKbApp* app) { app->usb_prev_mode = furi_hal_usb_get_config(); furi_hal_usb_set_config(NULL, NULL); @@ -636,13 +653,22 @@ void bad_kb_connection_init(BadKbApp* app) { bt_timeout = bt_hid_delays[LevelRssi39_0]; bt_disconnect(app->bt); // furi_delay_ms(200); - bt_keys_storage_set_storage_path(app->bt, HID_BT_KEYS_STORAGE_PATH); + bt_keys_storage_set_storage_path(app->bt, BAD_KB_APP_PATH_BOUND_KEYS_FILE); + app->bt_prev_mode = furi_hal_bt_get_profile_pairing_method(FuriHalBtProfileHidKeyboard); + if (app->bonding) { // usefull if bounding become an XTREME setting + uint8_t mac[6] = BAD_KB_BOUND_MAC_ADDRESS; + furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, mac); + // using GapPairingNone breaks bounding between devices + furi_hal_bt_set_profile_pairing_method(FuriHalBtProfileHidKeyboard, GapPairingPinCodeVerifyYesNo); + } else { + furi_hal_bt_set_profile_pairing_method(FuriHalBtProfileHidKeyboard, GapPairingNone); + } + bt_set_profile(app->bt, BtProfileHidKeyboard); - app->bt_prev_mode = bt_get_profile_pairing_method(app->bt); - bt_set_profile_pairing_method(app->bt, GapPairingNone); - bt_disable_peer_key_update(app->bt); // disable peer key adding to bt SRAM storage if(app->is_bt) { furi_hal_bt_start_advertising(); + if (!app->bonding) + bt_disable_peer_key_update(app->bt); // disable peer key adding to bt SRAM storage } else { furi_hal_bt_stop_advertising(); } @@ -659,11 +685,16 @@ void bad_kb_connection_deinit(BadKbApp* app) { bt_disconnect(app->bt); // stop ble // furi_delay_ms(200); // Wait 2nd core to update nvm storage bt_keys_storage_set_default_path(app->bt); - bt_set_profile_pairing_method(app->bt, app->bt_prev_mode); + if (app->bonding) { + // hal primitives doesn't restarts ble, that's what we want cuz we are shutting down + furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, app->mac); + }else { + bt_enable_peer_key_update(app->bt); // starts saving peer keys (bounded devices) + } // fails if ble radio stack isn't ready when switching profile // if it happens, maybe we should increase the delay after bt_disconnect bt_set_profile(app->bt, BtProfileSerial); - bt_enable_peer_key_update(app->bt); // starts saving peer keys (bounded devices) + furi_hal_bt_set_profile_pairing_method(FuriHalBtProfileHidKeyboard, app->bt_prev_mode); } static int32_t bad_kb_worker(void* context) { diff --git a/applications/main/bad_kb/bad_kb_script.h b/applications/main/bad_kb/bad_kb_script.h index 5699e4189..2f9097cb7 100644 --- a/applications/main/bad_kb/bad_kb_script.h +++ b/applications/main/bad_kb/bad_kb_script.h @@ -36,6 +36,8 @@ typedef struct { void bad_kb_config_switch_mode(BadKbApp* app); +void bad_kb_config_switch_bonding_mode(BadKbApp *app); + void bad_kb_connection_init(BadKbApp* app); void bad_kb_connection_deinit(BadKbApp* app); diff --git a/applications/main/bad_kb/scenes/bad_kb_scene_config_bt.c b/applications/main/bad_kb/scenes/bad_kb_scene_config_bt.c index 1a867f877..fa2a8ec8d 100644 --- a/applications/main/bad_kb/scenes/bad_kb_scene_config_bt.c +++ b/applications/main/bad_kb/scenes/bad_kb_scene_config_bt.c @@ -5,6 +5,7 @@ enum VarItemListIndex { VarItemListIndexConnection, + VarItemListIndexBonding, VarItemListIndexKeyboardLayout, VarItemListIndexAdvertisementName, VarItemListIndexMacAddress, @@ -19,6 +20,13 @@ void bad_kb_scene_config_bt_connection_callback(VariableItem* item) { view_dispatcher_send_custom_event(bad_kb->view_dispatcher, VarItemListIndexConnection); } +void bad_kb_scene_config_bt_bounding_callback(VariableItem* item) { + BadKbApp* bad_kb = variable_item_get_context(item); + bad_kb->bonding = variable_item_get_current_value_index(item); + variable_item_set_current_value_text(item, bad_kb->bonding ? "Remember" : "Forget"); + view_dispatcher_send_custom_event(bad_kb->view_dispatcher, VarItemListIndexBonding); +} + void bad_kb_scene_config_bt_var_item_list_callback(void* context, uint32_t index) { BadKbApp* bad_kb = context; view_dispatcher_send_custom_event(bad_kb->view_dispatcher, index); @@ -34,11 +42,19 @@ void bad_kb_scene_config_bt_on_enter(void* context) { variable_item_set_current_value_index(item, bad_kb->is_bt); variable_item_set_current_value_text(item, bad_kb->is_bt ? "BT" : "USB"); + item = variable_item_list_add( + var_item_list, "Bonding", 2, bad_kb_scene_config_bt_bounding_callback, bad_kb); + variable_item_set_current_value_index(item, bad_kb->bonding); + variable_item_set_current_value_text(item, bad_kb->bonding ? "Remember" : "Forget"); + item = variable_item_list_add(var_item_list, "Keyboard layout", 0, NULL, bad_kb); item = variable_item_list_add(var_item_list, "BT device name", 0, NULL, bad_kb); - - item = variable_item_list_add(var_item_list, "BT MAC address", 0, NULL, bad_kb); + + // this doesn't update instantly when toggling between Bounding modes + if (!bad_kb->bonding) { + item = variable_item_list_add(var_item_list, "BT MAC address", 0, NULL, bad_kb); + } variable_item_list_set_enter_callback( var_item_list, bad_kb_scene_config_bt_var_item_list_callback, bad_kb); @@ -57,6 +73,8 @@ bool bad_kb_scene_config_bt_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneConfigLayout); } else if(event.event == VarItemListIndexConnection) { bad_kb_config_switch_mode(bad_kb); + } else if (event.event == VarItemListIndexBonding) { + bad_kb_config_switch_bonding_mode(bad_kb); } else if(event.event == VarItemListIndexAdvertisementName) { scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneConfigName); } else if(event.event == VarItemListIndexMacAddress) { diff --git a/applications/services/bt/bt_service/bt.c b/applications/services/bt/bt_service/bt.c index 7cef8e140..964eff28d 100644 --- a/applications/services/bt/bt_service/bt.c +++ b/applications/services/bt/bt_service/bt.c @@ -424,17 +424,15 @@ const uint8_t* bt_get_profile_mac_address(Bt* bt) { return furi_hal_bt_get_profile_mac_addr(get_hal_bt_profile(bt->profile)); } -bool bt_remote_rssi(Bt* bt, BtRssi* rssi) { +bool bt_remote_rssi(Bt* bt, uint8_t* rssi) { furi_assert(bt); - UNUSED(rssi); uint8_t rssi_val; uint32_t since = furi_hal_bt_get_conn_rssi(&rssi_val); if(since == 0) return false; - rssi->rssi = rssi_val; - rssi->since = since; + *rssi = rssi_val; return true; } @@ -456,6 +454,7 @@ void bt_disable_peer_key_update(Bt* bt) { } void bt_enable_peer_key_update(Bt* bt) { + furi_assert(bt); furi_hal_bt_set_key_storage_change_callback(bt_on_key_storage_change_callback, bt); } diff --git a/applications/services/bt/bt_service/bt.h b/applications/services/bt/bt_service/bt.h index a79c227f7..eb762dbf4 100644 --- a/applications/services/bt/bt_service/bt.h +++ b/applications/services/bt/bt_service/bt.h @@ -47,7 +47,7 @@ const char* bt_get_profile_adv_name(Bt* bt); void bt_set_profile_mac_address(Bt* bt, const uint8_t mac[6]); const uint8_t* bt_get_profile_mac_address(Bt* bt); -bool bt_remote_rssi(Bt* bt, BtRssi* rssi); +bool bt_remote_rssi(Bt* bt, uint8_t* rssi); void bt_set_profile_pairing_method(Bt* bt, GapPairing pairing_method); GapPairing bt_get_profile_pairing_method(Bt* bt); diff --git a/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c b/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c index 31921b9f3..c912f2e5d 100644 --- a/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c +++ b/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c @@ -1,5 +1,6 @@ #include "../bt_settings_app.h" #include +#include void bt_settings_scene_forget_dev_confirm_dialog_callback(DialogExResult result, void* context) { furi_assert(context); @@ -30,6 +31,11 @@ bool bt_settings_scene_forget_dev_confirm_on_event(void* context, SceneManagerEv consumed = scene_manager_previous_scene(app->scene_manager); } else if(event.event == DialogExResultRight) { bt_forget_bonded_devices(app->bt); + // also removes keys of badkb bonded devices + bt_keys_storage_set_storage_path(app->bt, BAD_KB_APP_PATH_BOUND_KEYS_FILE); + bt_forget_bonded_devices(app->bt); + bt_keys_storage_set_default_path(app->bt); + scene_manager_next_scene(app->scene_manager, BtSettingsAppSceneForgetDevSuccess); consumed = true; } diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 2db05fc50..68f0ce8ab 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,14.1,, +Version,+,15.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -589,7 +589,7 @@ Function,+,bt_get_profile_mac_address,const uint8_t*,Bt* Function,+,bt_get_profile_pairing_method,GapPairing,Bt* Function,+,bt_keys_storage_set_default_path,void,Bt* Function,+,bt_keys_storage_set_storage_path,void,"Bt*, const char*" -Function,+,bt_remote_rssi,_Bool,"Bt*, BtRssi*" +Function,+,bt_remote_rssi,_Bool,"Bt*, uint8_t*" Function,+,bt_set_profile,_Bool,"Bt*, BtProfile" Function,+,bt_set_profile_adv_name,void,"Bt*, const char*, ..." Function,+,bt_set_profile_mac_address,void,"Bt*, const uint8_t[6]" diff --git a/firmware/targets/f7/ble_glue/gap.c b/firmware/targets/f7/ble_glue/gap.c index 0a317b574..ebf27b369 100644 --- a/firmware/targets/f7/ble_glue/gap.c +++ b/firmware/targets/f7/ble_glue/gap.c @@ -373,6 +373,7 @@ static void gap_init_svc(Gap* gap) { bool keypress_supported = false; uint8_t conf_mitm = CFG_MITM_PROTECTION; uint8_t conf_used_fixed_pin = CFG_USED_FIXED_PIN; + bool conf_bonding = gap->config->bonding_mode; if(gap->config->pairing_method == GapPairingPinCodeShow) { aci_gap_set_io_capability(IO_CAP_DISPLAY_ONLY); } else if(gap->config->pairing_method == GapPairingPinCodeVerifyYesNo) { @@ -382,6 +383,7 @@ static void gap_init_svc(Gap* gap) { // Just works pairing method (IOS accept it, it seems android and linux doesn't) conf_mitm = 0; conf_used_fixed_pin = 0; + conf_bonding = false; // if just works isn't supported, we want the numeric comparaison method aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO); keypress_supported = true; @@ -389,7 +391,7 @@ static void gap_init_svc(Gap* gap) { // Setup authentication aci_gap_set_authentication_requirement( - gap->config->bonding_mode, + conf_bonding, conf_mitm, CFG_SC_SUPPORT, keypress_supported,