[FL-1952] BLE bonding fix (#805)
* furi-hal-bt: add mutex guarding core2 state * ble-glue: configure ble keys storage in SRAM2 * bt: add load and save ble keys in internal storage * bt: improve work furi_hal_bt API * bt: rework app_entry -> ble_glue * bt: apply changes for f6 target * desktop: remove furi check * ble-glue: comment NVM in SRAM2 configuration * FuriHal: fix flash controller state corruption, fix incorrect semaphore release, implement C1-C2 flash controller access according to spec. Gui: change logging level. * Libs: better lfs integration with lfs_config. * Ble: switch C2 NVM to RAM. * FuriHalCrypto: ensure that core2 is alive before sending shci commands * Ble: fix incorrect nvm buffer size Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "bt_i.h"
|
||||
#include "battery_service.h"
|
||||
#include "bt_keys_storage.h"
|
||||
|
||||
#define BT_SERVICE_TAG "BT"
|
||||
|
||||
@@ -161,6 +162,14 @@ static void bt_on_gap_event_callback(BleEvent event, void* context) {
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_on_key_storage_change_callback(uint8_t* addr, uint16_t size, void* context) {
|
||||
furi_assert(context);
|
||||
Bt* bt = context;
|
||||
FURI_LOG_I(BT_SERVICE_TAG, "Changed addr start: %08lX, size changed: %d", addr, size);
|
||||
BtMessage message = {.type = BtMessageTypeKeysStorageUpdated};
|
||||
furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK);
|
||||
}
|
||||
|
||||
static void bt_statusbar_update(Bt* bt) {
|
||||
if(bt->status == BtStatusAdvertising) {
|
||||
view_port_set_width(bt->statusbar_view_port, icon_get_width(&I_Bluetooth_5x8));
|
||||
@@ -177,7 +186,12 @@ int32_t bt_srv() {
|
||||
Bt* bt = bt_alloc();
|
||||
furi_record_create("bt", bt);
|
||||
|
||||
if(!furi_hal_bt_wait_startup()) {
|
||||
// Read keys
|
||||
if(!bt_load_key_storage(bt)) {
|
||||
FURI_LOG_W(BT_SERVICE_TAG, "Failed to load saved bonding keys");
|
||||
}
|
||||
// Start 2nd core
|
||||
if(!furi_hal_bt_start_core2()) {
|
||||
FURI_LOG_E(BT_SERVICE_TAG, "Core2 startup failed");
|
||||
} else {
|
||||
view_port_enabled_set(bt->statusbar_view_port, true);
|
||||
@@ -190,6 +204,8 @@ int32_t bt_srv() {
|
||||
FURI_LOG_E(BT_SERVICE_TAG, "BT App start failed");
|
||||
}
|
||||
}
|
||||
furi_hal_bt_set_key_storage_change_callback(bt_on_key_storage_change_callback, bt);
|
||||
|
||||
// Update statusbar
|
||||
bt_statusbar_update(bt);
|
||||
|
||||
@@ -207,6 +223,8 @@ int32_t bt_srv() {
|
||||
} else if(message.type == BtMessageTypePinCodeShow) {
|
||||
// Display PIN code
|
||||
bt_pin_code_show_event_handler(bt, message.data.pin_code);
|
||||
} else if(message.type == BtMessageTypeKeysStorageUpdated) {
|
||||
bt_save_key_storage(bt);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@@ -25,6 +25,7 @@ typedef enum {
|
||||
BtMessageTypeUpdateStatusbar,
|
||||
BtMessageTypeUpdateBatteryLevel,
|
||||
BtMessageTypePinCodeShow,
|
||||
BtMessageTypeKeysStorageUpdated,
|
||||
} BtMessageType;
|
||||
|
||||
typedef union {
|
||||
@@ -38,6 +39,8 @@ typedef struct {
|
||||
} BtMessage;
|
||||
|
||||
struct Bt {
|
||||
uint8_t* bt_keys_addr_start;
|
||||
uint16_t bt_keys_size;
|
||||
BtSettings bt_settings;
|
||||
BtStatus status;
|
||||
osMessageQueueId_t message_queue;
|
||||
|
41
applications/bt/bt_service/bt_keys_storage.c
Normal file
41
applications/bt/bt_service/bt_keys_storage.c
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "bt_keys_storage.h"
|
||||
#include <furi.h>
|
||||
#include <file-worker.h>
|
||||
|
||||
#define BT_KEYS_STORAGE_TAG "bt keys storage"
|
||||
#define BT_KEYS_STORAGE_PATH "/int/bt.keys"
|
||||
|
||||
bool bt_load_key_storage(Bt* bt) {
|
||||
furi_assert(bt);
|
||||
|
||||
bool file_loaded = false;
|
||||
furi_hal_bt_get_key_storage_buff(&bt->bt_keys_addr_start, &bt->bt_keys_size);
|
||||
|
||||
FileWorker* file_worker = file_worker_alloc(true);
|
||||
if(file_worker_open(file_worker, BT_KEYS_STORAGE_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
furi_hal_bt_nvm_sram_sem_acquire();
|
||||
if(file_worker_read(file_worker, bt->bt_keys_addr_start, bt->bt_keys_size)) {
|
||||
file_loaded = true;
|
||||
}
|
||||
furi_hal_bt_nvm_sram_sem_release();
|
||||
}
|
||||
file_worker_free(file_worker);
|
||||
return file_loaded;
|
||||
}
|
||||
|
||||
bool bt_save_key_storage(Bt* bt) {
|
||||
furi_assert(bt);
|
||||
furi_assert(bt->bt_keys_addr_start);
|
||||
|
||||
bool file_saved = false;
|
||||
FileWorker* file_worker = file_worker_alloc(true);
|
||||
if(file_worker_open(file_worker, BT_KEYS_STORAGE_PATH, FSAM_WRITE, FSOM_OPEN_ALWAYS)) {
|
||||
furi_hal_bt_nvm_sram_sem_acquire();
|
||||
if(file_worker_write(file_worker, bt->bt_keys_addr_start, bt->bt_keys_size)) {
|
||||
file_saved = true;
|
||||
}
|
||||
furi_hal_bt_nvm_sram_sem_release();
|
||||
}
|
||||
file_worker_free(file_worker);
|
||||
return file_saved;
|
||||
}
|
7
applications/bt/bt_service/bt_keys_storage.h
Normal file
7
applications/bt/bt_service/bt_keys_storage.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "bt_i.h"
|
||||
|
||||
bool bt_load_key_storage(Bt* bt);
|
||||
|
||||
bool bt_save_key_storage(Bt* bt);
|
@@ -122,8 +122,7 @@ int32_t desktop_srv(void* p) {
|
||||
if(!loaded) {
|
||||
furi_hal_lock_set(false);
|
||||
memset(&desktop->settings, 0, sizeof(desktop->settings));
|
||||
bool saved = SAVE_DESKTOP_SETTINGS(&desktop->settings);
|
||||
furi_check(saved);
|
||||
SAVE_DESKTOP_SETTINGS(&desktop->settings);
|
||||
}
|
||||
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain);
|
||||
|
@@ -4,9 +4,10 @@
|
||||
#include <math.h>
|
||||
#include <toolbox/saved_struct.h>
|
||||
|
||||
#define DOLPHIN_STORE_PATH "/int/dolphin.state"
|
||||
#define DOLPHIN_STORE_HEADER_MAGIC 0xD0
|
||||
#define DOLPHIN_STORE_HEADER_VERSION 0x01
|
||||
#define DOLPHIN_STATE_TAG "DolphinState"
|
||||
#define DOLPHIN_STATE_PATH "/int/dolphin.state"
|
||||
#define DOLPHIN_STATE_HEADER_MAGIC 0xD0
|
||||
#define DOLPHIN_STATE_HEADER_VERSION 0x01
|
||||
#define DOLPHIN_LVL_THRESHOLD 20.0f
|
||||
|
||||
typedef struct {
|
||||
@@ -35,28 +36,42 @@ void dolphin_state_free(DolphinState* dolphin_state) {
|
||||
}
|
||||
|
||||
bool dolphin_state_save(DolphinState* dolphin_state) {
|
||||
return saved_struct_save(
|
||||
DOLPHIN_STORE_PATH,
|
||||
if(!dolphin_state->dirty) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool result = saved_struct_save(
|
||||
DOLPHIN_STATE_PATH,
|
||||
&dolphin_state->data,
|
||||
sizeof(DolphinStoreData),
|
||||
DOLPHIN_STORE_HEADER_MAGIC,
|
||||
DOLPHIN_STORE_HEADER_VERSION);
|
||||
DOLPHIN_STATE_HEADER_MAGIC,
|
||||
DOLPHIN_STATE_HEADER_VERSION);
|
||||
|
||||
if(result) {
|
||||
FURI_LOG_I(DOLPHIN_STATE_TAG, "State saved");
|
||||
dolphin_state->dirty = false;
|
||||
} else {
|
||||
FURI_LOG_E(DOLPHIN_STATE_TAG, "Failed to save state");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool dolphin_state_load(DolphinState* dolphin_state) {
|
||||
bool loaded = saved_struct_load(
|
||||
DOLPHIN_STORE_PATH,
|
||||
DOLPHIN_STATE_PATH,
|
||||
&dolphin_state->data,
|
||||
sizeof(DolphinStoreData),
|
||||
DOLPHIN_STORE_HEADER_MAGIC,
|
||||
DOLPHIN_STORE_HEADER_VERSION);
|
||||
DOLPHIN_STATE_HEADER_MAGIC,
|
||||
DOLPHIN_STATE_HEADER_VERSION);
|
||||
|
||||
if(!loaded) {
|
||||
FURI_LOG_W("dolphin-state", "Reset dolphin-state");
|
||||
FURI_LOG_W(DOLPHIN_STATE_TAG, "Reset dolphin-state");
|
||||
memset(dolphin_state, 0, sizeof(*dolphin_state));
|
||||
dolphin_state_save(dolphin_state);
|
||||
dolphin_state->dirty = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
return loaded;
|
||||
}
|
||||
|
||||
uint64_t dolphin_state_timestamp() {
|
||||
|
@@ -189,7 +189,7 @@ void gui_input(Gui* gui, InputEvent* input_event) {
|
||||
} else if(input_event->type == InputTypePress) {
|
||||
gui->ongoing_input |= key_bit;
|
||||
} else if(!(gui->ongoing_input & key_bit)) {
|
||||
FURI_LOG_W(
|
||||
FURI_LOG_D(
|
||||
"Gui",
|
||||
"non-complementary input, discarding key: %s type: %s, sequence: %p",
|
||||
input_get_key_name(input_event->key),
|
||||
@@ -211,7 +211,7 @@ void gui_input(Gui* gui, InputEvent* input_event) {
|
||||
if(view_port && view_port == gui->ongoing_input_view_port) {
|
||||
view_port_input(view_port, input_event);
|
||||
} else if(gui->ongoing_input_view_port && input_event->type == InputTypeRelease) {
|
||||
FURI_LOG_W(
|
||||
FURI_LOG_D(
|
||||
"Gui",
|
||||
"ViewPort changed while key press %p -> %p. Sending key: %s, type: %s, sequence: %p to previous view port",
|
||||
gui->ongoing_input_view_port,
|
||||
@@ -221,7 +221,7 @@ void gui_input(Gui* gui, InputEvent* input_event) {
|
||||
input_event->sequence);
|
||||
view_port_input(gui->ongoing_input_view_port, input_event);
|
||||
} else {
|
||||
FURI_LOG_W(
|
||||
FURI_LOG_D(
|
||||
"Gui",
|
||||
"ViewPort changed while key press %p -> %p. Discarding key: %s, type: %s, sequence: %p",
|
||||
gui->ongoing_input_view_port,
|
||||
|
@@ -236,7 +236,7 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e
|
||||
} else if(event->type == InputTypeRelease) {
|
||||
view_dispatcher->ongoing_input &= ~key_bit;
|
||||
} else if(!(view_dispatcher->ongoing_input & key_bit)) {
|
||||
FURI_LOG_W(
|
||||
FURI_LOG_D(
|
||||
"ViewDispatcher",
|
||||
"non-complementary input, discarding key: %s, type: %s, sequence: %p",
|
||||
input_get_key_name(event->key),
|
||||
@@ -275,7 +275,7 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e
|
||||
}
|
||||
}
|
||||
} else if(view_dispatcher->ongoing_input_view && event->type == InputTypeRelease) {
|
||||
FURI_LOG_W(
|
||||
FURI_LOG_D(
|
||||
"ViewDispatcher",
|
||||
"View changed while key press %p -> %p. Sending key: %s, type: %s, sequence: %p to previous view port",
|
||||
view_dispatcher->ongoing_input_view,
|
||||
|
@@ -119,7 +119,7 @@ static int storage_int_device_erase(const struct lfs_config* c, lfs_block_t bloc
|
||||
LFSData* lfs_data = c->context;
|
||||
size_t page = lfs_data->start_page + block;
|
||||
|
||||
FURI_LOG_D(TAG, "Device erase: page %d, translated page: %d", block, page);
|
||||
FURI_LOG_D(TAG, "Device erase: page %d, translated page: %x", block, page);
|
||||
|
||||
if(furi_hal_flash_erase(page, 1)) {
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user