[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:
gornekich
2021-11-04 20:26:41 +03:00
committed by GitHub
parent bb9c464a13
commit 3225f40870
39 changed files with 1184 additions and 568 deletions

View File

@@ -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;

View File

@@ -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;

View 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;
}

View 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);

View File

@@ -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);

View File

@@ -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() {

View File

@@ -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,

View File

@@ -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,

View File

@@ -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;