From 23ff6723cf870b999b75caee06b9f95a34c52534 Mon Sep 17 00:00:00 2001 From: gornekich Date: Fri, 21 Jan 2022 20:32:03 +0300 Subject: [PATCH] [FL-2204] Bluetooth forget devices (#967) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * bt: update connection parameters * bt: set correct connection latency and timeout * gui popup: add clean method * furi_hal_bt: add connection parameters request, clear database * bt: add forget bonded devices API * bt_settings: add forget bonded devices GUI * bt: rework pin code show with view port to hide view * bt: support conn parameters for different profiles * furi_hal_bt: sync f6 target * target f6: fix build * bt: format sources * furi_hal_bt: update connection parameters * bt: update connection params, fix GUI * FuriHal: fix spelling * Refactoring: rename _clean to _reset Co-authored-by: あく --- .../archive/scenes/archive_scene_rename.c | 2 +- applications/bt/bt_service/bt.c | 70 ++++++++++++++----- applications/bt/bt_service/bt.h | 7 ++ applications/bt/bt_service/bt_api.c | 6 ++ applications/bt/bt_service/bt_i.h | 5 +- applications/bt/bt_service/bt_keys_storage.c | 13 ++++ applications/bt/bt_service/bt_keys_storage.h | 2 + .../bt/bt_settings_app/bt_settings_app.c | 25 ++++++- .../bt/bt_settings_app/bt_settings_app.h | 13 +++- .../scenes/bt_settings_scene_config.h | 2 + .../bt_settings_scene_forget_dev_confirm.c | 44 ++++++++++++ .../bt_settings_scene_forget_dev_success.c | 43 ++++++++++++ .../scenes/bt_settings_scene_start.c | 23 ++++-- .../scenes/desktop_settings_scene_favorite.c | 4 +- .../desktop_settings_scene_pincode_menu.c | 4 +- .../scenes/desktop_settings_scene_start.c | 2 +- applications/gpio/scenes/gpio_scene_start.c | 2 +- .../gpio/scenes/gpio_scene_usb_uart_config.c | 2 +- applications/gui/modules/button_menu.c | 2 +- applications/gui/modules/button_menu.h | 2 +- applications/gui/modules/button_panel.c | 4 +- applications/gui/modules/button_panel.h | 2 +- applications/gui/modules/dialog_ex.c | 2 +- applications/gui/modules/dialog_ex.h | 4 +- applications/gui/modules/menu.c | 4 +- applications/gui/modules/menu.h | 2 +- applications/gui/modules/popup.c | 18 ++++- applications/gui/modules/popup.h | 6 ++ applications/gui/modules/submenu.c | 2 +- applications/gui/modules/submenu.h | 2 +- applications/gui/modules/text_box.c | 2 +- applications/gui/modules/text_box.h | 2 +- applications/gui/modules/text_input.c | 4 +- applications/gui/modules/text_input.h | 4 +- applications/gui/modules/variable_item_list.c | 2 +- applications/gui/modules/variable_item_list.h | 2 +- .../ibutton/scene/ibutton_scene_add_type.cpp | 4 +- .../scene/ibutton_scene_readed_key_menu.cpp | 4 +- .../ibutton/scene/ibutton_scene_save_name.cpp | 4 +- .../scene/ibutton_scene_saved_key_menu.cpp | 4 +- .../ibutton/scene/ibutton_scene_start.cpp | 4 +- .../irda/scene/irda_app_scene_edit.cpp | 2 +- .../scene/irda_app_scene_edit_key_select.cpp | 2 +- .../irda/scene/irda_app_scene_remote.cpp | 2 +- .../irda/scene/irda_app_scene_start.cpp | 2 +- .../irda/scene/irda_app_scene_universal.cpp | 2 +- .../scene/irda_app_scene_universal_common.cpp | 2 +- applications/loader/loader.c | 2 +- applications/nfc/scenes/nfc_scene_card_menu.c | 2 +- .../nfc/scenes/nfc_scene_device_info.c | 2 +- .../nfc/scenes/nfc_scene_mifare_ul_menu.c | 2 +- .../scenes/nfc_scene_read_mifare_ul_success.c | 2 +- applications/nfc/scenes/nfc_scene_save_name.c | 2 +- .../nfc/scenes/nfc_scene_saved_menu.c | 2 +- .../nfc/scenes/nfc_scene_scripts_menu.c | 2 +- applications/nfc/scenes/nfc_scene_set_type.c | 2 +- applications/nfc/scenes/nfc_scene_start.c | 2 +- .../scenes/power_settings_scene_power_off.c | 2 +- .../scenes/power_settings_scene_reboot.c | 2 +- .../scenes/power_settings_scene_start.c | 2 +- .../scenes/storage_settings_scene_start.c | 2 +- .../subghz/scenes/subghz_scene_more_raw.c | 2 +- .../subghz/scenes/subghz_scene_receiver.c | 2 +- .../scenes/subghz_scene_receiver_config.c | 2 +- .../subghz/scenes/subghz_scene_save_name.c | 2 +- .../subghz/scenes/subghz_scene_saved_menu.c | 2 +- .../subghz/scenes/subghz_scene_set_type.c | 2 +- .../subghz/scenes/subghz_scene_start.c | 2 +- .../subghz/scenes/subghz_scene_test.c | 2 +- applications/subghz/subghz_history.c | 4 +- applications/subghz/subghz_history.h | 2 +- firmware/targets/f6/ble_glue/gap.c | 46 +++++++++--- firmware/targets/f6/ble_glue/gap.h | 8 +++ firmware/targets/f6/furi_hal/furi_hal_bt.c | 25 +++++++ firmware/targets/f6/target.mk | 1 + firmware/targets/f7/ble_glue/gap.c | 46 +++++++++--- firmware/targets/f7/ble_glue/gap.h | 8 +++ firmware/targets/f7/furi_hal/furi_hal_bt.c | 25 +++++++ firmware/targets/f7/target.mk | 1 + .../targets/furi_hal_include/furi_hal_bt.h | 6 ++ .../view_modules/submenu_vm.cpp | 2 +- .../view_modules/text_input_vm.cpp | 2 +- 82 files changed, 471 insertions(+), 116 deletions(-) mode change 100644 => 100755 applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h create mode 100755 applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c create mode 100755 applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c mode change 100644 => 100755 firmware/targets/f6/ble_glue/gap.c mode change 100644 => 100755 firmware/targets/f6/furi_hal/furi_hal_bt.c mode change 100644 => 100755 firmware/targets/f7/ble_glue/gap.c mode change 100644 => 100755 firmware/targets/f7/furi_hal/furi_hal_bt.c diff --git a/applications/archive/scenes/archive_scene_rename.c b/applications/archive/scenes/archive_scene_rename.c index ad7669bc..99ae8be4 100644 --- a/applications/archive/scenes/archive_scene_rename.c +++ b/applications/archive/scenes/archive_scene_rename.c @@ -75,5 +75,5 @@ bool archive_scene_rename_on_event(void* context, SceneManagerEvent event) { void archive_scene_rename_on_exit(void* context) { ArchiveApp* archive = (ArchiveApp*)context; // Clear view - text_input_clean(archive->text_input); + text_input_reset(archive->text_input); } diff --git a/applications/bt/bt_service/bt.c b/applications/bt/bt_service/bt.c index 5448c81b..32008f52 100755 --- a/applications/bt/bt_service/bt.c +++ b/applications/bt/bt_service/bt.c @@ -2,7 +2,8 @@ #include "battery_service.h" #include "bt_keys_storage.h" -#include +#include +#include #define TAG "BtSrv" @@ -29,17 +30,46 @@ static ViewPort* bt_statusbar_view_port_alloc(Bt* bt) { return statusbar_view_port; } -static void bt_pin_code_show_event_handler(Bt* bt, uint32_t pin) { - furi_assert(bt); +static void bt_pin_code_view_port_draw_callback(Canvas* canvas, void* context) { + furi_assert(context); + Bt* bt = context; + char pin_code_info[24]; + canvas_draw_icon(canvas, 0, 0, &I_BLE_Pairing_128x64); + snprintf(pin_code_info, sizeof(pin_code_info), "Pairing code\n%06ld", bt->pin_code); + elements_multiline_text_aligned(canvas, 64, 4, AlignCenter, AlignTop, pin_code_info); + elements_button_left(canvas, "Quit"); +} + +static void bt_pin_code_view_port_input_callback(InputEvent* event, void* context) { + furi_assert(context); + Bt* bt = context; + if(event->type == InputTypeShort) { + if(event->key == InputKeyLeft || event->key == InputKeyBack) { + view_port_enabled_set(bt->pin_code_view_port, false); + } + } +} + +static ViewPort* bt_pin_code_view_port_alloc(Bt* bt) { + ViewPort* view_port = view_port_alloc(); + view_port_draw_callback_set(view_port, bt_pin_code_view_port_draw_callback, bt); + view_port_input_callback_set(view_port, bt_pin_code_view_port_input_callback, bt); + view_port_enabled_set(view_port, false); + return view_port; +} + +static void bt_pin_code_show(Bt* bt, uint32_t pin_code) { + bt->pin_code = pin_code; notification_message(bt->notification, &sequence_display_on); - string_t pin_str; - dialog_message_set_icon(bt->dialog_message, &I_BLE_Pairing_128x64, 0, 0); - string_init_printf(pin_str, "Pairing code\n%06d", pin); - dialog_message_set_text( - bt->dialog_message, string_get_cstr(pin_str), 64, 4, AlignCenter, AlignTop); - dialog_message_set_buttons(bt->dialog_message, "Quit", NULL, NULL); - dialog_message_show(bt->dialogs, bt->dialog_message); - string_clear(pin_str); + gui_view_port_send_to_front(bt->gui, bt->pin_code_view_port); + view_port_enabled_set(bt->pin_code_view_port, true); +} + +static void bt_pin_code_hide(Bt* bt) { + bt->pin_code = 0; + if(view_port_is_enabled(bt->pin_code_view_port)) { + view_port_enabled_set(bt->pin_code_view_port, false); + } } static bool bt_pin_code_verify_event_handler(Bt* bt, uint32_t pin) { @@ -84,11 +114,14 @@ Bt* bt_alloc() { // Setup statusbar view port bt->statusbar_view_port = bt_statusbar_view_port_alloc(bt); + // Pin code view port + bt->pin_code_view_port = bt_pin_code_view_port_alloc(bt); // Notification bt->notification = furi_record_open("notification"); // Gui bt->gui = furi_record_open("gui"); gui_add_view_port(bt->gui, bt->statusbar_view_port, GuiLayerStatusBarLeft); + gui_add_view_port(bt->gui, bt->pin_code_view_port, GuiLayerFullscreen); // Dialogs bt->dialogs = furi_record_open("dialogs"); @@ -162,7 +195,7 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) { if(event.type == GapEventTypeConnected) { // Update status bar bt->status = BtStatusConnected; - BtMessage message = {.type = BtMessageTypeUpdateStatusbar}; + BtMessage message = {.type = BtMessageTypeUpdateStatus}; furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); if(bt->profile == BtProfileSerial) { // Open RPC session @@ -192,12 +225,12 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) { ret = true; } else if(event.type == GapEventTypeStartAdvertising) { bt->status = BtStatusAdvertising; - BtMessage message = {.type = BtMessageTypeUpdateStatusbar}; + BtMessage message = {.type = BtMessageTypeUpdateStatus}; furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); ret = true; } else if(event.type == GapEventTypeStopAdvertising) { bt->status = BtStatusOff; - BtMessage message = {.type = BtMessageTypeUpdateStatusbar}; + BtMessage message = {.type = BtMessageTypeUpdateStatus}; furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); ret = true; } else if(event.type == GapEventTypePinCodeShow) { @@ -313,9 +346,10 @@ int32_t bt_srv() { BtMessage message; while(1) { furi_check(osMessageQueueGet(bt->message_queue, &message, NULL, osWaitForever) == osOK); - if(message.type == BtMessageTypeUpdateStatusbar) { - // Update statusbar + if(message.type == BtMessageTypeUpdateStatus) { + // Update view ports bt_statusbar_update(bt); + bt_pin_code_hide(bt); if(bt->status_changed_cb) { bt->status_changed_cb(bt->status, bt->status_changed_ctx); } @@ -324,11 +358,13 @@ int32_t bt_srv() { furi_hal_bt_update_battery_level(message.data.battery_level); } else if(message.type == BtMessageTypePinCodeShow) { // Display PIN code - bt_pin_code_show_event_handler(bt, message.data.pin_code); + bt_pin_code_show(bt, message.data.pin_code); } else if(message.type == BtMessageTypeKeysStorageUpdated) { bt_save_key_storage(bt); } else if(message.type == BtMessageTypeSetProfile) { bt_change_profile(bt, &message); + } else if(message.type == BtMessageTypeForgetBondedDevices) { + bt_delete_key_storage(bt); } } return 0; diff --git a/applications/bt/bt_service/bt.h b/applications/bt/bt_service/bt.h index d928f8b1..e39717d6 100644 --- a/applications/bt/bt_service/bt.h +++ b/applications/bt/bt_service/bt.h @@ -41,6 +41,13 @@ bool bt_set_profile(Bt* bt, BtProfile profile); */ void bt_set_status_changed_callback(Bt* bt, BtStatusChangedCallback callback, void* context); +/** Forget bonded devices + * @note Leads to wipe ble key storage and deleting bt.keys + * + * @param bt Bt instance + */ +void bt_forget_bonded_devices(Bt* bt); + #ifdef __cplusplus } #endif diff --git a/applications/bt/bt_service/bt_api.c b/applications/bt/bt_service/bt_api.c index a4f67e04..96d72e63 100755 --- a/applications/bt/bt_service/bt_api.c +++ b/applications/bt/bt_service/bt_api.c @@ -20,3 +20,9 @@ void bt_set_status_changed_callback(Bt* bt, BtStatusChangedCallback callback, vo bt->status_changed_cb = callback; bt->status_changed_ctx = context; } + +void bt_forget_bonded_devices(Bt* bt) { + furi_assert(bt); + BtMessage message = {.type = BtMessageTypeForgetBondedDevices}; + furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); +} diff --git a/applications/bt/bt_service/bt_i.h b/applications/bt/bt_service/bt_i.h index bb81e92f..610c0905 100644 --- a/applications/bt/bt_service/bt_i.h +++ b/applications/bt/bt_service/bt_i.h @@ -19,11 +19,12 @@ #define BT_API_UNLOCK_EVENT (1UL << 0) typedef enum { - BtMessageTypeUpdateStatusbar, + BtMessageTypeUpdateStatus, BtMessageTypeUpdateBatteryLevel, BtMessageTypePinCodeShow, BtMessageTypeKeysStorageUpdated, BtMessageTypeSetProfile, + BtMessageTypeForgetBondedDevices, } BtMessageType; typedef union { @@ -49,6 +50,8 @@ struct Bt { NotificationApp* notification; Gui* gui; ViewPort* statusbar_view_port; + ViewPort* pin_code_view_port; + uint32_t pin_code; DialogsApp* dialogs; DialogMessage* dialog_message; Power* power; diff --git a/applications/bt/bt_service/bt_keys_storage.c b/applications/bt/bt_service/bt_keys_storage.c index acd32339..c712b65b 100644 --- a/applications/bt/bt_service/bt_keys_storage.c +++ b/applications/bt/bt_service/bt_keys_storage.c @@ -39,3 +39,16 @@ bool bt_save_key_storage(Bt* bt) { file_worker_free(file_worker); return file_saved; } + +bool bt_delete_key_storage(Bt* bt) { + furi_assert(bt); + bool delete_succeed = false; + + furi_hal_bt_stop_advertising(); + delete_succeed = furi_hal_bt_clear_white_list(); + if(bt->bt_settings.enabled) { + furi_hal_bt_start_advertising(); + } + + return delete_succeed; +} diff --git a/applications/bt/bt_service/bt_keys_storage.h b/applications/bt/bt_service/bt_keys_storage.h index 4b09d7f2..e763e6a7 100644 --- a/applications/bt/bt_service/bt_keys_storage.h +++ b/applications/bt/bt_service/bt_keys_storage.h @@ -5,3 +5,5 @@ bool bt_load_key_storage(Bt* bt); bool bt_save_key_storage(Bt* bt); + +bool bt_delete_key_storage(Bt* bt); diff --git a/applications/bt/bt_settings_app/bt_settings_app.c b/applications/bt/bt_settings_app/bt_settings_app.c index f3e60937..be57223e 100755 --- a/applications/bt/bt_settings_app/bt_settings_app.c +++ b/applications/bt/bt_settings_app/bt_settings_app.c @@ -18,7 +18,9 @@ BtSettingsApp* bt_settings_app_alloc() { // Load settings bt_settings_load(&app->settings); app->gui = furi_record_open("gui"); + app->bt = furi_record_open("bt"); + // View Dispatcher and Scene Manager app->view_dispatcher = view_dispatcher_alloc(); app->scene_manager = scene_manager_alloc(&bt_settings_scene_handlers, app); view_dispatcher_enable_queue(app->view_dispatcher); @@ -31,26 +33,45 @@ BtSettingsApp* bt_settings_app_alloc() { view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + // Gui Modules app->var_item_list = variable_item_list_alloc(); view_dispatcher_add_view( app->view_dispatcher, BtSettingsAppViewVarItemList, variable_item_list_get_view(app->var_item_list)); + app->dialog = dialog_ex_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, BtSettingsAppViewDialog, dialog_ex_get_view(app->dialog)); + + app->popup = popup_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, BtSettingsAppViewPopup, popup_get_view(app->popup)); + + // Set first scene scene_manager_next_scene(app->scene_manager, BtSettingsAppSceneStart); return app; } void bt_settings_app_free(BtSettingsApp* app) { furi_assert(app); - // Variable item list + // Gui modules view_dispatcher_remove_view(app->view_dispatcher, BtSettingsAppViewVarItemList); variable_item_list_free(app->var_item_list); - // View dispatcher + + view_dispatcher_remove_view(app->view_dispatcher, BtSettingsAppViewDialog); + dialog_ex_free(app->dialog); + + view_dispatcher_remove_view(app->view_dispatcher, BtSettingsAppViewPopup); + popup_free(app->popup); + + // View Dispatcher and Scene Manager view_dispatcher_free(app->view_dispatcher); scene_manager_free(app->scene_manager); + // Records furi_record_close("gui"); + furi_record_close("bt"); free(app); } diff --git a/applications/bt/bt_settings_app/bt_settings_app.h b/applications/bt/bt_settings_app/bt_settings_app.h index 9f262a46..db379436 100755 --- a/applications/bt/bt_settings_app/bt_settings_app.h +++ b/applications/bt/bt_settings_app/bt_settings_app.h @@ -1,22 +1,33 @@ #pragma once #include +#include #include #include #include #include #include +#include +#include #include "../bt_settings.h" #include "scenes/bt_settings_scene.h" typedef struct { BtSettings settings; + Bt* bt; Gui* gui; SceneManager* scene_manager; ViewDispatcher* view_dispatcher; + VariableItemList* var_item_list; + DialogEx* dialog; + Popup* popup; } BtSettingsApp; -typedef enum { BtSettingsAppViewVarItemList } BtSettingsAppView; +typedef enum { + BtSettingsAppViewVarItemList, + BtSettingsAppViewDialog, + BtSettingsAppViewPopup, +} BtSettingsAppView; diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h b/applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h old mode 100644 new mode 100755 index 6aa23850..f78dd0c2 --- a/applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h +++ b/applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h @@ -1 +1,3 @@ ADD_SCENE(bt_settings, start, Start) +ADD_SCENE(bt_settings, forget_dev_confirm, ForgetDevConfirm) +ADD_SCENE(bt_settings, forget_dev_success, ForgetDevSuccess) diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c b/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c new file mode 100755 index 00000000..be9a7196 --- /dev/null +++ b/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c @@ -0,0 +1,44 @@ +#include "../bt_settings_app.h" +#include "furi_hal_bt.h" + +void bt_settings_scene_forget_dev_confirm_dialog_callback(DialogExResult result, void* context) { + furi_assert(context); + BtSettingsApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, result); +} + +void bt_settings_scene_forget_dev_confirm_on_enter(void* context) { + BtSettingsApp* app = context; + DialogEx* dialog = app->dialog; + dialog_ex_set_header(dialog, "Unpair all devices?", 64, 3, AlignCenter, AlignTop); + dialog_ex_set_text( + dialog, "All previous pairings\nwill be lost.", 64, 22, AlignCenter, AlignTop); + dialog_ex_set_left_button_text(dialog, "Back"); + dialog_ex_set_right_button_text(dialog, "Unpair"); + dialog_ex_set_context(dialog, app); + dialog_ex_set_result_callback(dialog, bt_settings_scene_forget_dev_confirm_dialog_callback); + + view_dispatcher_switch_to_view(app->view_dispatcher, BtSettingsAppViewDialog); +} + +bool bt_settings_scene_forget_dev_confirm_on_event(void* context, SceneManagerEvent event) { + BtSettingsApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == DialogExResultLeft) { + consumed = scene_manager_previous_scene(app->scene_manager); + } else if(event.event == DialogExResultRight) { + bt_forget_bonded_devices(app->bt); + scene_manager_next_scene(app->scene_manager, BtSettingsAppSceneForgetDevSuccess); + consumed = true; + } + } + + return consumed; +} + +void bt_settings_scene_forget_dev_confirm_on_exit(void* context) { + BtSettingsApp* app = context; + dialog_ex_reset(app->dialog); +} diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c b/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c new file mode 100755 index 00000000..e43082af --- /dev/null +++ b/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c @@ -0,0 +1,43 @@ +#include "../bt_settings_app.h" +#include "furi_hal_bt.h" + +#define SCENE_FORGET_DEV_SUCCESS_CUSTOM_EVENT (0UL) + +void bt_settings_app_scene_forget_dev_success_popup_callback(void* context) { + BtSettingsApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_FORGET_DEV_SUCCESS_CUSTOM_EVENT); +} + +void bt_settings_scene_forget_dev_success_on_enter(void* context) { + BtSettingsApp* app = context; + Popup* popup = app->popup; + + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); + popup_set_header(popup, "Done", 14, 15, AlignLeft, AlignTop); + popup_set_timeout(popup, 1500); + popup_set_context(popup, app); + popup_set_callback(popup, bt_settings_app_scene_forget_dev_success_popup_callback); + popup_enable_timeout(popup); + view_dispatcher_switch_to_view(app->view_dispatcher, BtSettingsAppViewPopup); +} + +bool bt_settings_scene_forget_dev_success_on_event(void* context, SceneManagerEvent event) { + BtSettingsApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SCENE_FORGET_DEV_SUCCESS_CUSTOM_EVENT) { + if(scene_manager_has_previous_scene(app->scene_manager, BtSettingsAppSceneStart)) { + consumed = scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, BtSettingsAppSceneStart); + } + } + } + + return consumed; +} + +void bt_settings_scene_forget_dev_success_on_exit(void* context) { + BtSettingsApp* app = context; + popup_reset(app->popup); +} diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c b/applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c index 0c809965..33c0bb5a 100755 --- a/applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c +++ b/applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c @@ -1,6 +1,8 @@ #include "../bt_settings_app.h" #include "furi_hal_bt.h" +#define SCENE_START_FORGET_DEV_SELECTED_EVENT (10UL) + enum BtSetting { BtSettingOff, BtSettingOn, @@ -8,8 +10,8 @@ enum BtSetting { }; const char* const bt_settings_text[BtSettingNum] = { - "Off", - "On", + "OFF", + "ON", }; static void bt_settings_scene_start_var_list_change_callback(VariableItem* item) { @@ -20,6 +22,12 @@ static void bt_settings_scene_start_var_list_change_callback(VariableItem* item) view_dispatcher_send_custom_event(app->view_dispatcher, index); } +static void bt_settings_scene_start_var_list_enter_callback(void* context, uint32_t index) { + furi_assert(context); + BtSettingsApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_START_FORGET_DEV_SELECTED_EVENT); +} + void bt_settings_scene_start_on_enter(void* context) { BtSettingsApp* app = context; VariableItemList* var_item_list = app->var_item_list; @@ -40,6 +48,9 @@ void bt_settings_scene_start_on_enter(void* context) { variable_item_set_current_value_index(item, BtSettingOff); variable_item_set_current_value_text(item, bt_settings_text[BtSettingOff]); } + variable_item_list_add(var_item_list, "Forget all paired devices", 1, NULL, NULL); + variable_item_list_set_enter_callback( + var_item_list, bt_settings_scene_start_var_list_enter_callback, app); } else { item = variable_item_list_add(var_item_list, "Bluetooth", 1, NULL, NULL); variable_item_set_current_value_text(item, "Broken"); @@ -56,16 +67,20 @@ bool bt_settings_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.event == BtSettingOn) { furi_hal_bt_start_advertising(); app->settings.enabled = true; + consumed = true; } else if(event.event == BtSettingOff) { app->settings.enabled = false; furi_hal_bt_stop_advertising(); + consumed = true; + } else if(event.event == SCENE_START_FORGET_DEV_SELECTED_EVENT) { + scene_manager_next_scene(app->scene_manager, BtSettingsAppSceneForgetDevConfirm); + consumed = true; } - consumed = true; } return consumed; } void bt_settings_scene_start_on_exit(void* context) { BtSettingsApp* app = context; - variable_item_list_clean(app->var_item_list); + variable_item_list_reset(app->var_item_list); } diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_favorite.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_favorite.c index 0b9bb580..67d0f218 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_favorite.c +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_favorite.c @@ -10,7 +10,7 @@ static void desktop_settings_scene_favorite_submenu_callback(void* context, uint void desktop_settings_scene_favorite_on_enter(void* context) { DesktopSettingsApp* app = context; Submenu* submenu = app->submenu; - submenu_clean(submenu); + submenu_reset(submenu); for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) { submenu_add_item( @@ -45,5 +45,5 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e void desktop_settings_scene_favorite_on_exit(void* context) { DesktopSettingsApp* app = context; SAVE_DESKTOP_SETTINGS(&app->settings); - submenu_clean(app->submenu); + submenu_reset(app->submenu); } diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pincode_menu.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pincode_menu.c index 78c2eee9..252d3a51 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pincode_menu.c +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pincode_menu.c @@ -9,7 +9,7 @@ static void desktop_settings_scene_pincode_menu_submenu_callback(void* context, void desktop_settings_scene_pincode_menu_on_enter(void* context) { DesktopSettingsApp* app = context; Submenu* submenu = app->submenu; - submenu_clean(submenu); + submenu_reset(submenu); if(!app->settings.pincode.length) { submenu_add_item( @@ -74,5 +74,5 @@ bool desktop_settings_scene_pincode_menu_on_event(void* context, SceneManagerEve void desktop_settings_scene_pincode_menu_on_exit(void* context) { DesktopSettingsApp* app = context; - submenu_clean(app->submenu); + submenu_reset(app->submenu); } diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c index 43b541ac..008d908e 100755 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c @@ -53,5 +53,5 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even void desktop_settings_scene_start_on_exit(void* context) { DesktopSettingsApp* app = context; - submenu_clean(app->submenu); + submenu_reset(app->submenu); } diff --git a/applications/gpio/scenes/gpio_scene_start.c b/applications/gpio/scenes/gpio_scene_start.c index dfa215e6..d0adb35e 100644 --- a/applications/gpio/scenes/gpio_scene_start.c +++ b/applications/gpio/scenes/gpio_scene_start.c @@ -95,5 +95,5 @@ bool gpio_scene_start_on_event(void* context, SceneManagerEvent event) { void gpio_scene_start_on_exit(void* context) { GpioApp* app = context; - variable_item_list_clean(app->var_item_list); + variable_item_list_reset(app->var_item_list); } diff --git a/applications/gpio/scenes/gpio_scene_usb_uart_config.c b/applications/gpio/scenes/gpio_scene_usb_uart_config.c index 713e6bed..72f6db69 100644 --- a/applications/gpio/scenes/gpio_scene_usb_uart_config.c +++ b/applications/gpio/scenes/gpio_scene_usb_uart_config.c @@ -135,6 +135,6 @@ void gpio_scene_usb_uart_cfg_on_exit(void* context) { app->scene_manager, GpioAppViewUsbUartCfg, variable_item_list_get_selected_item_index(app->var_item_list)); - variable_item_list_clean(app->var_item_list); + variable_item_list_reset(app->var_item_list); free(cfg_set); } diff --git a/applications/gui/modules/button_menu.c b/applications/gui/modules/button_menu.c index 0dbb1366..605e73eb 100644 --- a/applications/gui/modules/button_menu.c +++ b/applications/gui/modules/button_menu.c @@ -241,7 +241,7 @@ View* button_menu_get_view(ButtonMenu* button_menu) { return button_menu->view; } -void button_menu_clean(ButtonMenu* button_menu) { +void button_menu_reset(ButtonMenu* button_menu) { furi_assert(button_menu); with_view_model( diff --git a/applications/gui/modules/button_menu.h b/applications/gui/modules/button_menu.h index a662114b..bdf445d0 100644 --- a/applications/gui/modules/button_menu.h +++ b/applications/gui/modules/button_menu.h @@ -39,7 +39,7 @@ View* button_menu_get_view(ButtonMenu* button_menu); * * @param button_menu ButtonMenu instance */ -void button_menu_clean(ButtonMenu* button_menu); +void button_menu_reset(ButtonMenu* button_menu); /** Add item to button menu instance * diff --git a/applications/gui/modules/button_panel.c b/applications/gui/modules/button_panel.c index c3352d11..075e0c76 100644 --- a/applications/gui/modules/button_panel.c +++ b/applications/gui/modules/button_panel.c @@ -112,7 +112,7 @@ void button_panel_reserve(ButtonPanel* button_panel, size_t reserve_x, size_t re void button_panel_free(ButtonPanel* button_panel) { furi_assert(button_panel); - button_panel_clean(button_panel); + button_panel_reset(button_panel); with_view_model( button_panel->view, (ButtonPanelModel * model) { @@ -125,7 +125,7 @@ void button_panel_free(ButtonPanel* button_panel) { free(button_panel); } -void button_panel_clean(ButtonPanel* button_panel) { +void button_panel_reset(ButtonPanel* button_panel) { furi_assert(button_panel); with_view_model( diff --git a/applications/gui/modules/button_panel.h b/applications/gui/modules/button_panel.h index 479aeeaf..71ffdf3b 100644 --- a/applications/gui/modules/button_panel.h +++ b/applications/gui/modules/button_panel.h @@ -39,7 +39,7 @@ void button_panel_free(ButtonPanel* button_panel); * * @param button_panel ButtonPanel instance */ -void button_panel_clean(ButtonPanel* button_panel); +void button_panel_reset(ButtonPanel* button_panel); /** Reserve space for adding items. * diff --git a/applications/gui/modules/dialog_ex.c b/applications/gui/modules/dialog_ex.c index 71375030..5dd0e410 100755 --- a/applications/gui/modules/dialog_ex.c +++ b/applications/gui/modules/dialog_ex.c @@ -244,7 +244,7 @@ void dialog_ex_set_right_button_text(DialogEx* dialog_ex, const char* text) { }); } -void dialog_ex_clean(DialogEx* dialog_ex) { +void dialog_ex_reset(DialogEx* dialog_ex) { furi_assert(dialog_ex); TextElement clean_text_el = { .text = NULL, .x = 0, .y = 0, .horizontal = AlignLeft, .vertical = AlignLeft}; diff --git a/applications/gui/modules/dialog_ex.h b/applications/gui/modules/dialog_ex.h index 1420fe5f..871bb28a 100644 --- a/applications/gui/modules/dialog_ex.h +++ b/applications/gui/modules/dialog_ex.h @@ -143,8 +143,8 @@ void dialog_ex_set_right_button_text(DialogEx* dialog_ex, const char* text); * * @param dialog_ex DialogEx instance */ -void dialog_ex_clean(DialogEx* dialog_ex); +void dialog_ex_reset(DialogEx* dialog_ex); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/gui/modules/menu.c b/applications/gui/modules/menu.c index 6df2b94a..0fb95d70 100644 --- a/applications/gui/modules/menu.c +++ b/applications/gui/modules/menu.c @@ -146,7 +146,7 @@ Menu* menu_alloc() { void menu_free(Menu* menu) { furi_assert(menu); - menu_clean(menu); + menu_reset(menu); view_free(menu->view); free(menu); } @@ -180,7 +180,7 @@ void menu_add_item( }); } -void menu_clean(Menu* menu) { +void menu_reset(Menu* menu) { furi_assert(menu); with_view_model( menu->view, (MenuModel * model) { diff --git a/applications/gui/modules/menu.h b/applications/gui/modules/menu.h index b41930fd..f66514a7 100755 --- a/applications/gui/modules/menu.h +++ b/applications/gui/modules/menu.h @@ -59,7 +59,7 @@ void menu_add_item( * * @param menu Menu instance */ -void menu_clean(Menu* menu); +void menu_reset(Menu* menu); /** Set current menu item * diff --git a/applications/gui/modules/popup.c b/applications/gui/modules/popup.c index 766fdf67..0e3b3889 100644 --- a/applications/gui/modules/popup.c +++ b/applications/gui/modules/popup.c @@ -226,4 +226,20 @@ void popup_enable_timeout(Popup* popup) { void popup_disable_timeout(Popup* popup) { popup->timer_enabled = false; -} \ No newline at end of file +} + +void popup_reset(Popup* popup) { + furi_assert(popup); + + with_view_model( + popup->view, (PopupModel * model) { + memset(&model->header, 0, sizeof(model->header)); + memset(&model->text, 0, sizeof(model->text)); + memset(&model->icon, 0, sizeof(model->icon)); + return false; + }); + popup->callback = NULL; + popup->context = NULL; + popup->timer_enabled = false; + popup->timer_period_in_ms = 0; +} diff --git a/applications/gui/modules/popup.h b/applications/gui/modules/popup.h index 2b87f0ad..94f49a2b 100644 --- a/applications/gui/modules/popup.h +++ b/applications/gui/modules/popup.h @@ -123,6 +123,12 @@ void popup_enable_timeout(Popup* popup); */ void popup_disable_timeout(Popup* popup); +/** Reset popup instance state + * + * @param popup Popup instance + */ +void popup_reset(Popup* popup); + #ifdef __cplusplus } #endif diff --git a/applications/gui/modules/submenu.c b/applications/gui/modules/submenu.c index 9d2f5f44..e9e27203 100644 --- a/applications/gui/modules/submenu.c +++ b/applications/gui/modules/submenu.c @@ -177,7 +177,7 @@ void submenu_add_item( }); } -void submenu_clean(Submenu* submenu) { +void submenu_reset(Submenu* submenu) { furi_assert(submenu); with_view_model( diff --git a/applications/gui/modules/submenu.h b/applications/gui/modules/submenu.h index fac29e15..f68abe83 100644 --- a/applications/gui/modules/submenu.h +++ b/applications/gui/modules/submenu.h @@ -57,7 +57,7 @@ void submenu_add_item( * * @param submenu Submenu instance */ -void submenu_clean(Submenu* submenu); +void submenu_reset(Submenu* submenu); /** Set submenu item selector * diff --git a/applications/gui/modules/text_box.c b/applications/gui/modules/text_box.c index 67bb042c..40a8c382 100755 --- a/applications/gui/modules/text_box.c +++ b/applications/gui/modules/text_box.c @@ -164,7 +164,7 @@ View* text_box_get_view(TextBox* text_box) { return text_box->view; } -void text_box_clean(TextBox* text_box) { +void text_box_reset(TextBox* text_box) { furi_assert(text_box); with_view_model( diff --git a/applications/gui/modules/text_box.h b/applications/gui/modules/text_box.h index 9aaa0485..6928adcb 100644 --- a/applications/gui/modules/text_box.h +++ b/applications/gui/modules/text_box.h @@ -44,7 +44,7 @@ View* text_box_get_view(TextBox* text_box); * * @param text_box TextBox instance */ -void text_box_clean(TextBox* text_box); +void text_box_reset(TextBox* text_box); /** Set text for text_box * diff --git a/applications/gui/modules/text_input.c b/applications/gui/modules/text_input.c index e8351ce3..bb200606 100755 --- a/applications/gui/modules/text_input.c +++ b/applications/gui/modules/text_input.c @@ -425,7 +425,7 @@ TextInput* text_input_alloc() { return false; }); - text_input_clean(text_input); + text_input_reset(text_input); return text_input; } @@ -450,7 +450,7 @@ void text_input_free(TextInput* text_input) { free(text_input); } -void text_input_clean(TextInput* text_input) { +void text_input_reset(TextInput* text_input) { furi_assert(text_input); with_view_model( text_input->view, (TextInputModel * model) { diff --git a/applications/gui/modules/text_input.h b/applications/gui/modules/text_input.h index 7b0dc5c0..d30fcd4c 100644 --- a/applications/gui/modules/text_input.h +++ b/applications/gui/modules/text_input.h @@ -36,7 +36,7 @@ void text_input_free(TextInput* text_input); * * @param text_input Text input instance */ -void text_input_clean(TextInput* text_input); +void text_input_reset(TextInput* text_input); /** Get text input view * @@ -84,4 +84,4 @@ void text_input_set_header_text(TextInput* text_input, const char* text); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/gui/modules/variable_item_list.c b/applications/gui/modules/variable_item_list.c index b8d3a45d..cf2b01a1 100644 --- a/applications/gui/modules/variable_item_list.c +++ b/applications/gui/modules/variable_item_list.c @@ -312,7 +312,7 @@ void variable_item_list_free(VariableItemList* variable_item_list) { free(variable_item_list); } -void variable_item_list_clean(VariableItemList* variable_item_list) { +void variable_item_list_reset(VariableItemList* variable_item_list) { furi_assert(variable_item_list); with_view_model( diff --git a/applications/gui/modules/variable_item_list.h b/applications/gui/modules/variable_item_list.h index 86878273..78c7769c 100755 --- a/applications/gui/modules/variable_item_list.h +++ b/applications/gui/modules/variable_item_list.h @@ -32,7 +32,7 @@ void variable_item_list_free(VariableItemList* variable_item_list); * * @param variable_item_list VariableItemList instance */ -void variable_item_list_clean(VariableItemList* variable_item_list); +void variable_item_list_reset(VariableItemList* variable_item_list); /** Get VariableItemList View instance * diff --git a/applications/ibutton/scene/ibutton_scene_add_type.cpp b/applications/ibutton/scene/ibutton_scene_add_type.cpp index 4414be85..0c573f41 100644 --- a/applications/ibutton/scene/ibutton_scene_add_type.cpp +++ b/applications/ibutton/scene/ibutton_scene_add_type.cpp @@ -52,7 +52,7 @@ void iButtonSceneAddType::on_exit(iButtonApp* app) { iButtonAppViewManager* view = app->get_view_manager(); Submenu* submenu = view->get_submenu(); - submenu_clean(submenu); + submenu_reset(submenu); } void iButtonSceneAddType::submenu_callback(void* context, uint32_t index) { @@ -63,4 +63,4 @@ void iButtonSceneAddType::submenu_callback(void* context, uint32_t index) { event.payload.menu_index = index; app->get_view_manager()->send_event(&event); -} \ No newline at end of file +} diff --git a/applications/ibutton/scene/ibutton_scene_readed_key_menu.cpp b/applications/ibutton/scene/ibutton_scene_readed_key_menu.cpp index 2a8ea36c..e832c7e6 100644 --- a/applications/ibutton/scene/ibutton_scene_readed_key_menu.cpp +++ b/applications/ibutton/scene/ibutton_scene_readed_key_menu.cpp @@ -57,7 +57,7 @@ void iButtonSceneReadedKeyMenu::on_exit(iButtonApp* app) { iButtonAppViewManager* view = app->get_view_manager(); Submenu* submenu = view->get_submenu(); - submenu_clean(submenu); + submenu_reset(submenu); } void iButtonSceneReadedKeyMenu::submenu_callback(void* context, uint32_t index) { @@ -68,4 +68,4 @@ void iButtonSceneReadedKeyMenu::submenu_callback(void* context, uint32_t index) event.payload.menu_index = index; app->get_view_manager()->send_event(&event); -} \ No newline at end of file +} diff --git a/applications/ibutton/scene/ibutton_scene_save_name.cpp b/applications/ibutton/scene/ibutton_scene_save_name.cpp index a59ee552..5b85d409 100644 --- a/applications/ibutton/scene/ibutton_scene_save_name.cpp +++ b/applications/ibutton/scene/ibutton_scene_save_name.cpp @@ -48,7 +48,7 @@ bool iButtonSceneSaveName::on_event(iButtonApp* app, iButtonEvent* event) { void iButtonSceneSaveName::on_exit(iButtonApp* app) { TextInput* text_input = app->get_view_manager()->get_text_input(); - text_input_clean(text_input); + text_input_reset(text_input); } void iButtonSceneSaveName::text_input_callback(void* context) { @@ -58,4 +58,4 @@ void iButtonSceneSaveName::text_input_callback(void* context) { event.type = iButtonEvent::Type::EventTypeTextEditResult; app->get_view_manager()->send_event(&event); -} \ No newline at end of file +} diff --git a/applications/ibutton/scene/ibutton_scene_saved_key_menu.cpp b/applications/ibutton/scene/ibutton_scene_saved_key_menu.cpp index 80cf9565..8b797968 100644 --- a/applications/ibutton/scene/ibutton_scene_saved_key_menu.cpp +++ b/applications/ibutton/scene/ibutton_scene_saved_key_menu.cpp @@ -59,7 +59,7 @@ void iButtonSceneSavedKeyMenu::on_exit(iButtonApp* app) { iButtonAppViewManager* view = app->get_view_manager(); Submenu* submenu = view->get_submenu(); - submenu_clean(submenu); + submenu_reset(submenu); } void iButtonSceneSavedKeyMenu::submenu_callback(void* context, uint32_t index) { @@ -70,4 +70,4 @@ void iButtonSceneSavedKeyMenu::submenu_callback(void* context, uint32_t index) { event.payload.menu_index = index; app->get_view_manager()->send_event(&event); -} \ No newline at end of file +} diff --git a/applications/ibutton/scene/ibutton_scene_start.cpp b/applications/ibutton/scene/ibutton_scene_start.cpp index ccd2a90a..9d064aad 100644 --- a/applications/ibutton/scene/ibutton_scene_start.cpp +++ b/applications/ibutton/scene/ibutton_scene_start.cpp @@ -49,7 +49,7 @@ void iButtonSceneStart::on_exit(iButtonApp* app) { iButtonAppViewManager* view = app->get_view_manager(); Submenu* submenu = view->get_submenu(); - submenu_clean(submenu); + submenu_reset(submenu); } void iButtonSceneStart::submenu_callback(void* context, uint32_t index) { @@ -60,4 +60,4 @@ void iButtonSceneStart::submenu_callback(void* context, uint32_t index) { event.payload.menu_index = index; app->get_view_manager()->send_event(&event); -} \ No newline at end of file +} diff --git a/applications/irda/scene/irda_app_scene_edit.cpp b/applications/irda/scene/irda_app_scene_edit.cpp index a66bdc4b..bb26ca11 100644 --- a/applications/irda/scene/irda_app_scene_edit.cpp +++ b/applications/irda/scene/irda_app_scene_edit.cpp @@ -75,5 +75,5 @@ void IrdaAppSceneEdit::on_exit(IrdaApp* app) { IrdaAppViewManager* view_manager = app->get_view_manager(); Submenu* submenu = view_manager->get_submenu(); - submenu_clean(submenu); + submenu_reset(submenu); } diff --git a/applications/irda/scene/irda_app_scene_edit_key_select.cpp b/applications/irda/scene/irda_app_scene_edit_key_select.cpp index 33a74c8d..7d805cd6 100644 --- a/applications/irda/scene/irda_app_scene_edit_key_select.cpp +++ b/applications/irda/scene/irda_app_scene_edit_key_select.cpp @@ -53,5 +53,5 @@ void IrdaAppSceneEditKeySelect::on_exit(IrdaApp* app) { IrdaAppViewManager* view_manager = app->get_view_manager(); Submenu* submenu = view_manager->get_submenu(); - submenu_clean(submenu); + submenu_reset(submenu); } diff --git a/applications/irda/scene/irda_app_scene_remote.cpp b/applications/irda/scene/irda_app_scene_remote.cpp index a19235cb..c46d2e29 100644 --- a/applications/irda/scene/irda_app_scene_remote.cpp +++ b/applications/irda/scene/irda_app_scene_remote.cpp @@ -132,5 +132,5 @@ void IrdaAppSceneRemote::on_exit(IrdaApp* app) { IrdaAppViewManager* view_manager = app->get_view_manager(); ButtonMenu* button_menu = view_manager->get_button_menu(); - button_menu_clean(button_menu); + button_menu_reset(button_menu); } diff --git a/applications/irda/scene/irda_app_scene_start.cpp b/applications/irda/scene/irda_app_scene_start.cpp index be372d1b..62dcbbc5 100644 --- a/applications/irda/scene/irda_app_scene_start.cpp +++ b/applications/irda/scene/irda_app_scene_start.cpp @@ -62,5 +62,5 @@ void IrdaAppSceneStart::on_exit(IrdaApp* app) { Submenu* submenu = view_manager->get_submenu(); app->get_remote_manager()->reset_remote(); - submenu_clean(submenu); + submenu_reset(submenu); } diff --git a/applications/irda/scene/irda_app_scene_universal.cpp b/applications/irda/scene/irda_app_scene_universal.cpp index 65df44c6..01134400 100644 --- a/applications/irda/scene/irda_app_scene_universal.cpp +++ b/applications/irda/scene/irda_app_scene_universal.cpp @@ -53,5 +53,5 @@ void IrdaAppSceneUniversal::on_exit(IrdaApp* app) { IrdaAppViewManager* view_manager = app->get_view_manager(); Submenu* submenu = view_manager->get_submenu(); - submenu_clean(submenu); + submenu_reset(submenu); } diff --git a/applications/irda/scene/irda_app_scene_universal_common.cpp b/applications/irda/scene/irda_app_scene_universal_common.cpp index d61fb8ad..c55a7af7 100644 --- a/applications/irda/scene/irda_app_scene_universal_common.cpp +++ b/applications/irda/scene/irda_app_scene_universal_common.cpp @@ -102,5 +102,5 @@ bool IrdaAppSceneUniversalCommon::on_event(IrdaApp* app, IrdaAppEvent* event) { void IrdaAppSceneUniversalCommon::on_exit(IrdaApp* app) { IrdaAppViewManager* view_manager = app->get_view_manager(); ButtonPanel* button_panel = view_manager->get_button_panel(); - button_panel_clean(button_panel); + button_panel_reset(button_panel); } diff --git a/applications/loader/loader.c b/applications/loader/loader.c index 4cb2e209..f78e5bc0 100644 --- a/applications/loader/loader.c +++ b/applications/loader/loader.c @@ -429,7 +429,7 @@ void loader_show_menu() { } void loader_update_menu() { - menu_clean(loader_instance->primary_menu); + menu_reset(loader_instance->primary_menu); loader_build_menu(); } diff --git a/applications/nfc/scenes/nfc_scene_card_menu.c b/applications/nfc/scenes/nfc_scene_card_menu.c index 5724abdb..638b7192 100755 --- a/applications/nfc/scenes/nfc_scene_card_menu.c +++ b/applications/nfc/scenes/nfc_scene_card_menu.c @@ -81,5 +81,5 @@ bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) { void nfc_scene_card_menu_on_exit(void* context) { Nfc* nfc = (Nfc*)context; - submenu_clean(nfc->submenu); + submenu_reset(nfc->submenu); } diff --git a/applications/nfc/scenes/nfc_scene_device_info.c b/applications/nfc/scenes/nfc_scene_device_info.c index 81708847..4aea026b 100755 --- a/applications/nfc/scenes/nfc_scene_device_info.c +++ b/applications/nfc/scenes/nfc_scene_device_info.c @@ -199,7 +199,7 @@ void nfc_scene_device_info_on_exit(void* context) { dialog_ex_set_context(dialog_ex, NULL); } else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { // Clear TextBox - text_box_clean(nfc->text_box); + text_box_reset(nfc->text_box); string_reset(nfc->text_box_store); } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { // Clear Bank Card diff --git a/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c b/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c index 344d4733..f8b4f2f1 100755 --- a/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c +++ b/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c @@ -54,5 +54,5 @@ bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent event) { void nfc_scene_mifare_ul_menu_on_exit(void* context) { Nfc* nfc = (Nfc*)context; - submenu_clean(nfc->submenu); + submenu_reset(nfc->submenu); } diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c b/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c index a11af2b5..db5762ad 100755 --- a/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c +++ b/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c @@ -126,6 +126,6 @@ void nfc_scene_read_mifare_ul_success_on_exit(void* context) { // Clean TextBox TextBox* text_box = nfc->text_box; - text_box_clean(text_box); + text_box_reset(text_box); string_reset(nfc->text_box_store); } diff --git a/applications/nfc/scenes/nfc_scene_save_name.c b/applications/nfc/scenes/nfc_scene_save_name.c index 44babcdd..83a60e38 100755 --- a/applications/nfc/scenes/nfc_scene_save_name.c +++ b/applications/nfc/scenes/nfc_scene_save_name.c @@ -60,5 +60,5 @@ void nfc_scene_save_name_on_exit(void* context) { Nfc* nfc = (Nfc*)context; // Clear view - text_input_clean(nfc->text_input); + text_input_reset(nfc->text_input); } diff --git a/applications/nfc/scenes/nfc_scene_saved_menu.c b/applications/nfc/scenes/nfc_scene_saved_menu.c index ea38ce3d..5da82572 100755 --- a/applications/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/nfc/scenes/nfc_scene_saved_menu.c @@ -81,5 +81,5 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { void nfc_scene_saved_menu_on_exit(void* context) { Nfc* nfc = (Nfc*)context; - submenu_clean(nfc->submenu); + submenu_reset(nfc->submenu); } diff --git a/applications/nfc/scenes/nfc_scene_scripts_menu.c b/applications/nfc/scenes/nfc_scene_scripts_menu.c index ffb856d3..367b5c05 100755 --- a/applications/nfc/scenes/nfc_scene_scripts_menu.c +++ b/applications/nfc/scenes/nfc_scene_scripts_menu.c @@ -55,5 +55,5 @@ bool nfc_scene_scripts_menu_on_event(void* context, SceneManagerEvent event) { void nfc_scene_scripts_menu_on_exit(void* context) { Nfc* nfc = (Nfc*)context; - submenu_clean(nfc->submenu); + submenu_reset(nfc->submenu); } diff --git a/applications/nfc/scenes/nfc_scene_set_type.c b/applications/nfc/scenes/nfc_scene_set_type.c index 66eafe83..0e6624bd 100755 --- a/applications/nfc/scenes/nfc_scene_set_type.c +++ b/applications/nfc/scenes/nfc_scene_set_type.c @@ -45,5 +45,5 @@ bool nfc_scene_set_type_on_event(void* context, SceneManagerEvent event) { void nfc_scene_set_type_on_exit(void* context) { Nfc* nfc = (Nfc*)context; - submenu_clean(nfc->submenu); + submenu_reset(nfc->submenu); } diff --git a/applications/nfc/scenes/nfc_scene_start.c b/applications/nfc/scenes/nfc_scene_start.c index b99580d2..40f3a12e 100644 --- a/applications/nfc/scenes/nfc_scene_start.c +++ b/applications/nfc/scenes/nfc_scene_start.c @@ -78,5 +78,5 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) { void nfc_scene_start_on_exit(void* context) { Nfc* nfc = (Nfc*)context; - submenu_clean(nfc->submenu); + submenu_reset(nfc->submenu); } diff --git a/applications/power/power_settings_app/scenes/power_settings_scene_power_off.c b/applications/power/power_settings_app/scenes/power_settings_scene_power_off.c index a389778a..2c79bcfe 100755 --- a/applications/power/power_settings_app/scenes/power_settings_scene_power_off.c +++ b/applications/power/power_settings_app/scenes/power_settings_scene_power_off.c @@ -39,5 +39,5 @@ bool power_settings_scene_power_off_on_event(void* context, SceneManagerEvent ev void power_settings_scene_power_off_on_exit(void* context) { PowerSettingsApp* app = context; - dialog_ex_clean(app->dialog); + dialog_ex_reset(app->dialog); } diff --git a/applications/power/power_settings_app/scenes/power_settings_scene_reboot.c b/applications/power/power_settings_app/scenes/power_settings_scene_reboot.c index d6ec2d04..8edc8138 100755 --- a/applications/power/power_settings_app/scenes/power_settings_scene_reboot.c +++ b/applications/power/power_settings_app/scenes/power_settings_scene_reboot.c @@ -48,5 +48,5 @@ bool power_settings_scene_reboot_on_event(void* context, SceneManagerEvent event void power_settings_scene_reboot_on_exit(void* context) { PowerSettingsApp* app = context; - submenu_clean(app->submenu); + submenu_reset(app->submenu); } diff --git a/applications/power/power_settings_app/scenes/power_settings_scene_start.c b/applications/power/power_settings_app/scenes/power_settings_scene_start.c index c2ae256f..1b368dbc 100755 --- a/applications/power/power_settings_app/scenes/power_settings_scene_start.c +++ b/applications/power/power_settings_app/scenes/power_settings_scene_start.c @@ -60,5 +60,5 @@ bool power_settings_scene_start_on_event(void* context, SceneManagerEvent event) void power_settings_scene_start_on_exit(void* context) { PowerSettingsApp* app = context; - submenu_clean(app->submenu); + submenu_reset(app->submenu); } diff --git a/applications/storage_settings/scenes/storage_settings_scene_start.c b/applications/storage_settings/scenes/storage_settings_scene_start.c index 595c73f1..027a5998 100644 --- a/applications/storage_settings/scenes/storage_settings_scene_start.c +++ b/applications/storage_settings/scenes/storage_settings_scene_start.c @@ -115,5 +115,5 @@ bool storage_settings_scene_start_on_event(void* context, SceneManagerEvent even void storage_settings_scene_start_on_exit(void* context) { StorageSettings* app = context; - submenu_clean(app->submenu); + submenu_reset(app->submenu); } diff --git a/applications/subghz/scenes/subghz_scene_more_raw.c b/applications/subghz/scenes/subghz_scene_more_raw.c index 10e0aad4..1047aef2 100644 --- a/applications/subghz/scenes/subghz_scene_more_raw.c +++ b/applications/subghz/scenes/subghz_scene_more_raw.c @@ -56,5 +56,5 @@ bool subghz_scene_more_raw_on_event(void* context, SceneManagerEvent event) { void subghz_scene_more_raw_on_exit(void* context) { SubGhz* subghz = context; - submenu_clean(subghz->submenu); + submenu_reset(subghz->submenu); } diff --git a/applications/subghz/scenes/subghz_scene_receiver.c b/applications/subghz/scenes/subghz_scene_receiver.c index a2eb4af2..4ffa29fc 100644 --- a/applications/subghz/scenes/subghz_scene_receiver.c +++ b/applications/subghz/scenes/subghz_scene_receiver.c @@ -66,7 +66,7 @@ void subghz_scene_receiver_on_enter(void* context) { string_init(str_buff); if(subghz->txrx->rx_key_state == SubGhzRxKeyStateIDLE) { - subghz_history_clean(subghz->txrx->history); + subghz_history_reset(subghz->txrx->history); } //Load history to receiver diff --git a/applications/subghz/scenes/subghz_scene_receiver_config.c b/applications/subghz/scenes/subghz_scene_receiver_config.c index 4243b09b..28afc1fb 100644 --- a/applications/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/subghz/scenes/subghz_scene_receiver_config.c @@ -161,7 +161,7 @@ bool subghz_scene_receiver_config_on_event(void* context, SceneManagerEvent even void subghz_scene_receiver_config_on_exit(void* context) { SubGhz* subghz = context; - variable_item_list_clean(subghz->variable_item_list); + variable_item_list_reset(subghz->variable_item_list); scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneReadRAW, SubghzCustomEventManagerNoSet); } diff --git a/applications/subghz/scenes/subghz_scene_save_name.c b/applications/subghz/scenes/subghz_scene_save_name.c index c64d0d2c..d473fed7 100644 --- a/applications/subghz/scenes/subghz_scene_save_name.c +++ b/applications/subghz/scenes/subghz_scene_save_name.c @@ -91,7 +91,7 @@ void subghz_scene_save_name_on_exit(void* context) { text_input_set_validator(subghz->text_input, NULL, NULL); validator_is_file_free(validator_context); - text_input_clean(subghz->text_input); + text_input_reset(subghz->text_input); scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneReadRAW, SubghzCustomEventManagerNoSet); } diff --git a/applications/subghz/scenes/subghz_scene_saved_menu.c b/applications/subghz/scenes/subghz_scene_saved_menu.c index c6623c6b..833bdfd5 100644 --- a/applications/subghz/scenes/subghz_scene_saved_menu.c +++ b/applications/subghz/scenes/subghz_scene_saved_menu.c @@ -67,5 +67,5 @@ bool subghz_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { void subghz_scene_saved_menu_on_exit(void* context) { SubGhz* subghz = context; - submenu_clean(subghz->submenu); + submenu_reset(subghz->submenu); } diff --git a/applications/subghz/scenes/subghz_scene_set_type.c b/applications/subghz/scenes/subghz_scene_set_type.c index ea88baf8..ddd8b976 100644 --- a/applications/subghz/scenes/subghz_scene_set_type.c +++ b/applications/subghz/scenes/subghz_scene_set_type.c @@ -202,5 +202,5 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { void subghz_scene_set_type_on_exit(void* context) { SubGhz* subghz = context; - submenu_clean(subghz->submenu); + submenu_reset(subghz->submenu); } diff --git a/applications/subghz/scenes/subghz_scene_start.c b/applications/subghz/scenes/subghz_scene_start.c index 454b39f1..14108e34 100644 --- a/applications/subghz/scenes/subghz_scene_start.c +++ b/applications/subghz/scenes/subghz_scene_start.c @@ -97,5 +97,5 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) { void subghz_scene_start_on_exit(void* context) { SubGhz* subghz = context; - submenu_clean(subghz->submenu); + submenu_reset(subghz->submenu); } diff --git a/applications/subghz/scenes/subghz_scene_test.c b/applications/subghz/scenes/subghz_scene_test.c index bef7e1e4..48c49e0e 100644 --- a/applications/subghz/scenes/subghz_scene_test.c +++ b/applications/subghz/scenes/subghz_scene_test.c @@ -57,5 +57,5 @@ bool subghz_scene_test_on_event(void* context, SceneManagerEvent event) { void subghz_scene_test_on_exit(void* context) { SubGhz* subghz = context; - submenu_clean(subghz->submenu); + submenu_reset(subghz->submenu); } diff --git a/applications/subghz/subghz_history.c b/applications/subghz/subghz_history.c index b9fb90e7..470bcea0 100644 --- a/applications/subghz/subghz_history.c +++ b/applications/subghz/subghz_history.c @@ -60,7 +60,7 @@ FuriHalSubGhzPreset subghz_history_get_preset(SubGhzHistory* instance, uint16_t return instance->history[idx].preset; } -void subghz_history_clean(SubGhzHistory* instance) { +void subghz_history_reset(SubGhzHistory* instance) { furi_assert(instance); instance->last_index_write = 0; instance->code_last_found = 0; @@ -168,4 +168,4 @@ bool subghz_history_add_to_history( instance->last_index_write++; return true; -} \ No newline at end of file +} diff --git a/applications/subghz/subghz_history.h b/applications/subghz/subghz_history.h index 59655188..462a9f4e 100644 --- a/applications/subghz/subghz_history.h +++ b/applications/subghz/subghz_history.h @@ -21,7 +21,7 @@ void subghz_history_free(SubGhzHistory* instance); * * @param instance - SubGhzHistory instance */ -void subghz_history_clean(SubGhzHistory* instance); +void subghz_history_reset(SubGhzHistory* instance); /** Set frequency and preset to history[idx] * diff --git a/firmware/targets/f6/ble_glue/gap.c b/firmware/targets/f6/ble_glue/gap.c old mode 100644 new mode 100755 index dfcd174e..d9a2096f --- a/firmware/targets/f6/ble_glue/gap.c +++ b/firmware/targets/f6/ble_glue/gap.c @@ -94,9 +94,17 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { case EVT_LE_META_EVENT: meta_evt = (evt_le_meta_event*)event_pckt->data; switch(meta_evt->subevent) { - case EVT_LE_CONN_UPDATE_COMPLETE: - FURI_LOG_D(TAG, "Connection update event"); + case EVT_LE_CONN_UPDATE_COMPLETE: { + hci_le_connection_update_complete_event_rp0* event = + (hci_le_connection_update_complete_event_rp0*)meta_evt->data; + FURI_LOG_I( + TAG, + "Connection interval: %d, latency: %d, supervision timeout: %d", + event->Conn_Interval, + event->Conn_Latency, + event->Supervision_Timeout); break; + } case EVT_LE_PHY_UPDATE_COMPLETE: evt_le_phy_update_complete = (hci_le_phy_update_complete_event_rp0*)meta_evt->data; @@ -129,6 +137,15 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { // Update connection status and handle gap->state = GapStateConnected; gap->service.connection_handle = connection_complete_event->Connection_Handle; + GapConnectionParams* params = &gap->config->conn_param; + if(aci_l2cap_connection_parameter_update_req( + gap->service.connection_handle, + params->conn_int_min, + params->conn_int_max, + params->slave_latency, + params->supervisor_timeout)) { + FURI_LOG_W(TAG, "Failed to request connection parameters update"); + } // Start pairing by sending security request aci_gap_slave_security_req(connection_complete_event->Connection_Handle); @@ -184,28 +201,28 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { } break; case EVT_BLUE_GAP_AUTHORIZATION_REQUEST: - FURI_LOG_I(TAG, "Authorization request event"); + FURI_LOG_D(TAG, "Authorization request event"); break; case EVT_BLUE_GAP_SLAVE_SECURITY_INITIATED: - FURI_LOG_I(TAG, "Slave security initiated"); + FURI_LOG_D(TAG, "Slave security initiated"); break; case EVT_BLUE_GAP_BOND_LOST: - FURI_LOG_I(TAG, "Bond lost event. Start rebonding"); + FURI_LOG_D(TAG, "Bond lost event. Start rebonding"); aci_gap_allow_rebond(gap->service.connection_handle); break; case EVT_BLUE_GAP_DEVICE_FOUND: - FURI_LOG_I(TAG, "Device found event"); + FURI_LOG_D(TAG, "Device found event"); break; case EVT_BLUE_GAP_ADDR_NOT_RESOLVED: - FURI_LOG_I(TAG, "Address not resolved event"); + FURI_LOG_D(TAG, "Address not resolved event"); break; case EVT_BLUE_GAP_KEYPRESS_NOTIFICATION: - FURI_LOG_I(TAG, "Key press notification event"); + FURI_LOG_D(TAG, "Key press notification event"); break; case EVT_BLUE_GAP_NUMERIC_COMPARISON_VALUE: { @@ -234,8 +251,19 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { break; case EVT_BLUE_GAP_PROCEDURE_COMPLETE: - FURI_LOG_I(TAG, "Procedure complete event"); + FURI_LOG_D(TAG, "Procedure complete event"); break; + + case EVT_BLUE_L2CAP_CONNECTION_UPDATE_RESP: { + uint16_t result = + ((aci_l2cap_connection_update_resp_event_rp0*)(blue_evt->data))->Result; + if(result == 0) { + FURI_LOG_D(TAG, "Connection parameters accepted"); + } else if(result == 1) { + FURI_LOG_D(TAG, "Connection parameters denied"); + } + break; + } } default: break; diff --git a/firmware/targets/f6/ble_glue/gap.h b/firmware/targets/f6/ble_glue/gap.h index 635a4c3c..1a2e7962 100644 --- a/firmware/targets/f6/ble_glue/gap.h +++ b/firmware/targets/f6/ble_glue/gap.h @@ -55,6 +55,13 @@ typedef enum { GapPairingPinCodeVerifyYesNo, } GapPairing; +typedef struct { + uint16_t conn_int_min; + uint16_t conn_int_max; + uint16_t slave_latency; + uint16_t supervisor_timeout; +} GapConnectionParams; + typedef struct { uint16_t adv_service_uuid; uint16_t appearance_char; @@ -62,6 +69,7 @@ typedef struct { GapPairing pairing_method; uint8_t mac_address[GAP_MAC_ADDR_SIZE]; char adv_name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH]; + GapConnectionParams conn_param; } GapConfig; bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context); diff --git a/firmware/targets/f6/furi_hal/furi_hal_bt.c b/firmware/targets/f6/furi_hal/furi_hal_bt.c old mode 100644 new mode 100755 index 7147c7f0..4465f15e --- a/firmware/targets/f6/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f6/furi_hal/furi_hal_bt.c @@ -42,6 +42,13 @@ FuriHalBtProfileConfig profile_config[FuriHalBtProfileNumber] = { .bonding_mode = true, .pairing_method = GapPairingPinCodeShow, .mac_address = FURI_HAL_BT_DEFAULT_MAC_ADDR, + .conn_param = + { + .conn_int_min = 0x08, + .conn_int_max = 0x18, + .slave_latency = 0, + .supervisor_timeout = 50, + }, }, }, [FuriHalBtProfileHidKeyboard] = @@ -55,6 +62,14 @@ FuriHalBtProfileConfig profile_config[FuriHalBtProfileNumber] = { .bonding_mode = true, .pairing_method = GapPairingPinCodeVerifyYesNo, .mac_address = FURI_HAL_BT_DEFAULT_MAC_ADDR, + // TODO optimize + .conn_param = + { + .conn_int_min = 0x12, + .conn_int_max = 0x1e, + .slave_latency = 6, + .supervisor_timeout = 700, + }, }, }, }; @@ -277,6 +292,16 @@ void furi_hal_bt_nvm_sram_sem_release() { HAL_HSEM_Release(CFG_HW_BLE_NVM_SRAM_SEMID, 0); } +bool furi_hal_bt_clear_white_list() { + furi_hal_bt_nvm_sram_sem_acquire(); + tBleStatus status = aci_gap_clear_security_db(); + if(status) { + FURI_LOG_E(TAG, "Clear while list failed with status %d", status); + } + furi_hal_bt_nvm_sram_sem_release(); + return status != BLE_STATUS_SUCCESS; +} + void furi_hal_bt_dump_state(string_t buffer) { if(furi_hal_bt_is_alive()) { uint8_t HCI_Version; diff --git a/firmware/targets/f6/target.mk b/firmware/targets/f6/target.mk index 029c8f40..0c9bd182 100644 --- a/firmware/targets/f6/target.mk +++ b/firmware/targets/f6/target.mk @@ -112,6 +112,7 @@ C_SOURCES += \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_gap_aci.c \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_gatt_aci.c \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_hal_aci.c \ + $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_l2cap_aci.c \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/tl_mbox.c \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/hci_tl.c \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/hci_tl_if.c \ diff --git a/firmware/targets/f7/ble_glue/gap.c b/firmware/targets/f7/ble_glue/gap.c old mode 100644 new mode 100755 index dfcd174e..d9a2096f --- a/firmware/targets/f7/ble_glue/gap.c +++ b/firmware/targets/f7/ble_glue/gap.c @@ -94,9 +94,17 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { case EVT_LE_META_EVENT: meta_evt = (evt_le_meta_event*)event_pckt->data; switch(meta_evt->subevent) { - case EVT_LE_CONN_UPDATE_COMPLETE: - FURI_LOG_D(TAG, "Connection update event"); + case EVT_LE_CONN_UPDATE_COMPLETE: { + hci_le_connection_update_complete_event_rp0* event = + (hci_le_connection_update_complete_event_rp0*)meta_evt->data; + FURI_LOG_I( + TAG, + "Connection interval: %d, latency: %d, supervision timeout: %d", + event->Conn_Interval, + event->Conn_Latency, + event->Supervision_Timeout); break; + } case EVT_LE_PHY_UPDATE_COMPLETE: evt_le_phy_update_complete = (hci_le_phy_update_complete_event_rp0*)meta_evt->data; @@ -129,6 +137,15 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { // Update connection status and handle gap->state = GapStateConnected; gap->service.connection_handle = connection_complete_event->Connection_Handle; + GapConnectionParams* params = &gap->config->conn_param; + if(aci_l2cap_connection_parameter_update_req( + gap->service.connection_handle, + params->conn_int_min, + params->conn_int_max, + params->slave_latency, + params->supervisor_timeout)) { + FURI_LOG_W(TAG, "Failed to request connection parameters update"); + } // Start pairing by sending security request aci_gap_slave_security_req(connection_complete_event->Connection_Handle); @@ -184,28 +201,28 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { } break; case EVT_BLUE_GAP_AUTHORIZATION_REQUEST: - FURI_LOG_I(TAG, "Authorization request event"); + FURI_LOG_D(TAG, "Authorization request event"); break; case EVT_BLUE_GAP_SLAVE_SECURITY_INITIATED: - FURI_LOG_I(TAG, "Slave security initiated"); + FURI_LOG_D(TAG, "Slave security initiated"); break; case EVT_BLUE_GAP_BOND_LOST: - FURI_LOG_I(TAG, "Bond lost event. Start rebonding"); + FURI_LOG_D(TAG, "Bond lost event. Start rebonding"); aci_gap_allow_rebond(gap->service.connection_handle); break; case EVT_BLUE_GAP_DEVICE_FOUND: - FURI_LOG_I(TAG, "Device found event"); + FURI_LOG_D(TAG, "Device found event"); break; case EVT_BLUE_GAP_ADDR_NOT_RESOLVED: - FURI_LOG_I(TAG, "Address not resolved event"); + FURI_LOG_D(TAG, "Address not resolved event"); break; case EVT_BLUE_GAP_KEYPRESS_NOTIFICATION: - FURI_LOG_I(TAG, "Key press notification event"); + FURI_LOG_D(TAG, "Key press notification event"); break; case EVT_BLUE_GAP_NUMERIC_COMPARISON_VALUE: { @@ -234,8 +251,19 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { break; case EVT_BLUE_GAP_PROCEDURE_COMPLETE: - FURI_LOG_I(TAG, "Procedure complete event"); + FURI_LOG_D(TAG, "Procedure complete event"); break; + + case EVT_BLUE_L2CAP_CONNECTION_UPDATE_RESP: { + uint16_t result = + ((aci_l2cap_connection_update_resp_event_rp0*)(blue_evt->data))->Result; + if(result == 0) { + FURI_LOG_D(TAG, "Connection parameters accepted"); + } else if(result == 1) { + FURI_LOG_D(TAG, "Connection parameters denied"); + } + break; + } } default: break; diff --git a/firmware/targets/f7/ble_glue/gap.h b/firmware/targets/f7/ble_glue/gap.h index 635a4c3c..1a2e7962 100644 --- a/firmware/targets/f7/ble_glue/gap.h +++ b/firmware/targets/f7/ble_glue/gap.h @@ -55,6 +55,13 @@ typedef enum { GapPairingPinCodeVerifyYesNo, } GapPairing; +typedef struct { + uint16_t conn_int_min; + uint16_t conn_int_max; + uint16_t slave_latency; + uint16_t supervisor_timeout; +} GapConnectionParams; + typedef struct { uint16_t adv_service_uuid; uint16_t appearance_char; @@ -62,6 +69,7 @@ typedef struct { GapPairing pairing_method; uint8_t mac_address[GAP_MAC_ADDR_SIZE]; char adv_name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH]; + GapConnectionParams conn_param; } GapConfig; bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context); diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt.c b/firmware/targets/f7/furi_hal/furi_hal_bt.c old mode 100644 new mode 100755 index 7147c7f0..4465f15e --- a/firmware/targets/f7/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt.c @@ -42,6 +42,13 @@ FuriHalBtProfileConfig profile_config[FuriHalBtProfileNumber] = { .bonding_mode = true, .pairing_method = GapPairingPinCodeShow, .mac_address = FURI_HAL_BT_DEFAULT_MAC_ADDR, + .conn_param = + { + .conn_int_min = 0x08, + .conn_int_max = 0x18, + .slave_latency = 0, + .supervisor_timeout = 50, + }, }, }, [FuriHalBtProfileHidKeyboard] = @@ -55,6 +62,14 @@ FuriHalBtProfileConfig profile_config[FuriHalBtProfileNumber] = { .bonding_mode = true, .pairing_method = GapPairingPinCodeVerifyYesNo, .mac_address = FURI_HAL_BT_DEFAULT_MAC_ADDR, + // TODO optimize + .conn_param = + { + .conn_int_min = 0x12, + .conn_int_max = 0x1e, + .slave_latency = 6, + .supervisor_timeout = 700, + }, }, }, }; @@ -277,6 +292,16 @@ void furi_hal_bt_nvm_sram_sem_release() { HAL_HSEM_Release(CFG_HW_BLE_NVM_SRAM_SEMID, 0); } +bool furi_hal_bt_clear_white_list() { + furi_hal_bt_nvm_sram_sem_acquire(); + tBleStatus status = aci_gap_clear_security_db(); + if(status) { + FURI_LOG_E(TAG, "Clear while list failed with status %d", status); + } + furi_hal_bt_nvm_sram_sem_release(); + return status != BLE_STATUS_SUCCESS; +} + void furi_hal_bt_dump_state(string_t buffer) { if(furi_hal_bt_is_alive()) { uint8_t HCI_Version; diff --git a/firmware/targets/f7/target.mk b/firmware/targets/f7/target.mk index 029c8f40..0c9bd182 100644 --- a/firmware/targets/f7/target.mk +++ b/firmware/targets/f7/target.mk @@ -112,6 +112,7 @@ C_SOURCES += \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_gap_aci.c \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_gatt_aci.c \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_hal_aci.c \ + $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_l2cap_aci.c \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/tl_mbox.c \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/hci_tl.c \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/hci_tl_if.c \ diff --git a/firmware/targets/furi_hal_include/furi_hal_bt.h b/firmware/targets/furi_hal_include/furi_hal_bt.h index cacf33a3..e10901b0 100644 --- a/firmware/targets/furi_hal_include/furi_hal_bt.h +++ b/firmware/targets/furi_hal_include/furi_hal_bt.h @@ -121,6 +121,12 @@ void furi_hal_bt_nvm_sram_sem_acquire(); */ void furi_hal_bt_nvm_sram_sem_release(); +/** Clear key storage + * + * @return true on success +*/ +bool furi_hal_bt_clear_white_list(); + /** Set key storage change callback * * @param callback BleGlueKeyStorageChangedCallback instance diff --git a/lib/app-scened-template/view_modules/submenu_vm.cpp b/lib/app-scened-template/view_modules/submenu_vm.cpp index ee6b4441..939bb6b1 100644 --- a/lib/app-scened-template/view_modules/submenu_vm.cpp +++ b/lib/app-scened-template/view_modules/submenu_vm.cpp @@ -13,7 +13,7 @@ View* SubmenuVM::get_view() { } void SubmenuVM::clean() { - submenu_clean(submenu); + submenu_reset(submenu); } void SubmenuVM::add_item( diff --git a/lib/app-scened-template/view_modules/text_input_vm.cpp b/lib/app-scened-template/view_modules/text_input_vm.cpp index 6777fb29..06f243de 100644 --- a/lib/app-scened-template/view_modules/text_input_vm.cpp +++ b/lib/app-scened-template/view_modules/text_input_vm.cpp @@ -13,7 +13,7 @@ View* TextInputVM::get_view() { } void TextInputVM::clean() { - text_input_clean(text_input); + text_input_reset(text_input); } void TextInputVM::set_result_callback(