diff --git a/Makefile b/Makefile index e067a3c6..062ed8ff 100644 --- a/Makefile +++ b/Makefile @@ -49,14 +49,14 @@ firmware_clean: .PHONY: bootloader_flash bootloader_flash: -ifeq ($(FORCE), '1') +ifeq ($(FORCE), 1) rm $(PROJECT_ROOT)/bootloader/.obj/f*/flash || true endif $(MAKE) -C $(PROJECT_ROOT)/bootloader -j$(NPROCS) flash .PHONY: firmware_flash firmware_flash: -ifeq ($(FORCE), '1') +ifeq ($(FORCE), 1) rm $(PROJECT_ROOT)/firmware/.obj/f*/flash || true endif $(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) flash diff --git a/applications/applications.c b/applications/applications.c index 9b269461..7cc105bb 100644 --- a/applications/applications.c +++ b/applications/applications.c @@ -65,55 +65,55 @@ extern int32_t power_settings_app(void* p); const FlipperApplication FLIPPER_SERVICES[] = { /* Services */ #ifdef SRV_RPC - {.app = rpc_srv, .name = "RPC", .stack_size = 1024 * 4, .icon = NULL}, + {.app = rpc_srv, .name = "RpcSrv", .stack_size = 1024 * 4, .icon = NULL}, #endif #ifdef SRV_BT - {.app = bt_srv, .name = "BT", .stack_size = 1024, .icon = NULL}, + {.app = bt_srv, .name = "BtSrv", .stack_size = 1024, .icon = NULL}, #endif #ifdef SRV_CLI - {.app = cli_srv, .name = "Cli", .stack_size = 4096, .icon = NULL}, + {.app = cli_srv, .name = "CliSrv", .stack_size = 4096, .icon = NULL}, #endif #ifdef SRV_DIALOGS - {.app = dialogs_srv, .name = "Dialogs", .stack_size = 1024, .icon = NULL}, + {.app = dialogs_srv, .name = "DialogsSrv", .stack_size = 1024, .icon = NULL}, #endif #ifdef SRV_DOLPHIN - {.app = dolphin_srv, .name = "Dolphin", .stack_size = 1024, .icon = NULL}, + {.app = dolphin_srv, .name = "DolphinSrv", .stack_size = 1024, .icon = NULL}, #endif #ifdef SRV_DESKTOP - {.app = desktop_srv, .name = "Desktop", .stack_size = 1024, .icon = NULL}, + {.app = desktop_srv, .name = "DesktopSrv", .stack_size = 2048, .icon = NULL}, #endif #ifdef SRV_GUI - {.app = gui_srv, .name = "Gui", .stack_size = 8192, .icon = NULL}, + {.app = gui_srv, .name = "GuiSrv", .stack_size = 2048, .icon = NULL}, #endif #ifdef SRV_INPUT - {.app = input_srv, .name = "Input", .stack_size = 1024, .icon = NULL}, + {.app = input_srv, .name = "InputSrv", .stack_size = 1024, .icon = NULL}, #endif #ifdef SRV_LOADER - {.app = loader_srv, .name = "Loader", .stack_size = 1024, .icon = NULL}, + {.app = loader_srv, .name = "LoaderSrv", .stack_size = 1024, .icon = NULL}, #endif #ifdef SRV_NOTIFICATION - {.app = notification_srv, .name = "Notification", .stack_size = 1024, .icon = NULL}, + {.app = notification_srv, .name = "NotificationSrv", .stack_size = 1536, .icon = NULL}, #endif #ifdef SRV_POWER - {.app = power_srv, .name = "Power", .stack_size = 1024, .icon = NULL}, + {.app = power_srv, .name = "PowerSrv", .stack_size = 1024, .icon = NULL}, #endif #ifdef SRV_POWER_OBSERVER - {.app = power_observer_srv, .name = "PowerObserver", .stack_size = 1024, .icon = NULL}, + {.app = power_observer_srv, .name = "PowerAuditSrv", .stack_size = 1024, .icon = NULL}, #endif #ifdef SRV_STORAGE - {.app = storage_srv, .name = "Storage", .stack_size = 4096, .icon = NULL}, + {.app = storage_srv, .name = "StorageSrv", .stack_size = 3072, .icon = NULL}, #endif }; diff --git a/applications/applications.mk b/applications/applications.mk index 1168ee82..4f0a5a67 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -231,6 +231,10 @@ endif SRV_RPC ?= 0 ifeq ($(SRV_RPC), 1) CFLAGS += -DSRV_RPC +ifeq ($(SRV_RPC_DEBUG), 1) +CFLAGS += -DSRV_RPC_DEBUG +endif +SRV_CLI = 1 endif SRV_LOADER ?= 0 diff --git a/applications/archive/helpers/archive_files.c b/applications/archive/helpers/archive_files.c index fc3508e8..83b67a5b 100644 --- a/applications/archive/helpers/archive_files.c +++ b/applications/archive/helpers/archive_files.c @@ -1,6 +1,8 @@ #include "archive_files.h" #include "archive_browser.h" +#define TAG "Archive" + bool filter_by_extension(FileInfo* file_info, const char* tab_ext, const char* name) { furi_assert(file_info); furi_assert(tab_ext); @@ -147,11 +149,11 @@ void archive_file_append(const char* path, const char* format, ...) { FileWorker* file_worker = file_worker_alloc(false); if(!file_worker_open(file_worker, path, FSAM_WRITE, FSOM_OPEN_APPEND)) { - FURI_LOG_E("Archive", "Append open error"); + FURI_LOG_E(TAG, "Append open error"); } if(!file_worker_write(file_worker, string_get_cstr(string), string_size(string))) { - FURI_LOG_E("Archive", "Append write error"); + FURI_LOG_E(TAG, "Append write error"); } file_worker_close(file_worker); diff --git a/applications/bt/bt_service/bt.c b/applications/bt/bt_service/bt.c index aa999e36..64966570 100755 --- a/applications/bt/bt_service/bt.c +++ b/applications/bt/bt_service/bt.c @@ -2,7 +2,7 @@ #include "battery_service.h" #include "bt_keys_storage.h" -#define BT_SERVICE_TAG "BT" +#define TAG "BtSrv" static void bt_draw_statusbar_callback(Canvas* canvas, void* context) { furi_assert(context); @@ -81,14 +81,15 @@ Bt* bt_alloc() { } // Called from GAP thread from Serial service -static void bt_on_data_received_callback(uint8_t* data, uint16_t size, void* context) { +static uint16_t bt_on_data_received_callback(uint8_t* data, uint16_t size, void* context) { furi_assert(context); Bt* bt = context; size_t bytes_processed = rpc_session_feed(bt->rpc_session, data, size, 1000); if(bytes_processed != size) { - FURI_LOG_E(BT_SERVICE_TAG, "Only %d of %d bytes processed by RPC", bytes_processed, size); + FURI_LOG_E(TAG, "Only %d of %d bytes processed by RPC", bytes_processed, size); } + return rpc_session_get_available_size(bt->rpc_session); } // Called from GAP thread from Serial service @@ -118,6 +119,11 @@ static void bt_rpc_send_bytes_callback(void* context, uint8_t* bytes, size_t byt } } +static void bt_rpc_buffer_is_empty_callback(void* context) { + furi_assert(context); + furi_hal_bt_notify_buffer_is_empty(); +} + // Called from GAP thread static void bt_on_gap_event_callback(BleEvent event, void* context) { furi_assert(context); @@ -129,12 +135,13 @@ static void bt_on_gap_event_callback(BleEvent event, void* context) { BtMessage message = {.type = BtMessageTypeUpdateStatusbar}; furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); // Open RPC session - FURI_LOG_I(BT_SERVICE_TAG, "Open RPC connection"); + FURI_LOG_I(TAG, "Open RPC connection"); bt->rpc_session = rpc_session_open(bt->rpc); rpc_session_set_send_bytes_callback(bt->rpc_session, bt_rpc_send_bytes_callback); + rpc_session_set_buffer_is_empty_callback(bt->rpc_session, bt_rpc_buffer_is_empty_callback); rpc_session_set_context(bt->rpc_session, bt); furi_hal_bt_set_data_event_callbacks( - bt_on_data_received_callback, bt_on_data_sent_callback, bt); + RPC_BUFFER_SIZE, bt_on_data_received_callback, bt_on_data_sent_callback, bt); // Update battery level PowerInfo info; power_get_info(bt->power, &info); @@ -142,7 +149,7 @@ static void bt_on_gap_event_callback(BleEvent event, void* context) { message.data.battery_level = info.charge; furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); } else if(event.type == BleEventTypeDisconnected) { - FURI_LOG_I(BT_SERVICE_TAG, "Close RPC connection"); + FURI_LOG_I(TAG, "Close RPC connection"); if(bt->rpc_session) { rpc_session_close(bt->rpc_session); bt->rpc_session = NULL; @@ -165,7 +172,7 @@ 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); + FURI_LOG_I(TAG, "Changed addr start: %08lX, size changed: %d", addr, size); BtMessage message = {.type = BtMessageTypeKeysStorageUpdated}; furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); } @@ -188,20 +195,20 @@ int32_t bt_srv() { // Read keys if(!bt_load_key_storage(bt)) { - FURI_LOG_W(BT_SERVICE_TAG, "Failed to load saved bonding keys"); + FURI_LOG_W(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"); + FURI_LOG_E(TAG, "Core2 startup failed"); } else { view_port_enabled_set(bt->statusbar_view_port, true); if(furi_hal_bt_init_app(bt_on_gap_event_callback, bt)) { - FURI_LOG_I(BT_SERVICE_TAG, "BLE stack started"); + FURI_LOG_I(TAG, "BLE stack started"); if(bt->bt_settings.enabled) { furi_hal_bt_start_advertising(); } } else { - FURI_LOG_E(BT_SERVICE_TAG, "BT App start failed"); + FURI_LOG_E(TAG, "BT App start failed"); } } furi_hal_bt_set_key_storage_change_callback(bt_on_key_storage_change_callback, bt); diff --git a/applications/bt/bt_settings.c b/applications/bt/bt_settings.c index bd6399a9..9c154c47 100644 --- a/applications/bt/bt_settings.c +++ b/applications/bt/bt_settings.c @@ -2,7 +2,7 @@ #include #include -#define BT_SETTINGS_TAG "bt settings" +#define TAG "BtSettings" #define BT_SETTINGS_PATH "/int/bt.settings" bool bt_settings_load(BtSettings* bt_settings) { @@ -10,7 +10,7 @@ bool bt_settings_load(BtSettings* bt_settings) { bool file_loaded = false; BtSettings settings = {}; - FURI_LOG_I(BT_SETTINGS_TAG, "Loading settings from \"%s\"", BT_SETTINGS_PATH); + FURI_LOG_I(TAG, "Loading settings from \"%s\"", BT_SETTINGS_PATH); FileWorker* file_worker = file_worker_alloc(true); if(file_worker_open(file_worker, BT_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { if(file_worker_read(file_worker, &settings, sizeof(settings))) { @@ -20,16 +20,16 @@ bool bt_settings_load(BtSettings* bt_settings) { file_worker_free(file_worker); if(file_loaded) { - FURI_LOG_I(BT_SETTINGS_TAG, "Settings load success"); + FURI_LOG_I(TAG, "Settings load success"); if(settings.version != BT_SETTINGS_VERSION) { - FURI_LOG_E(BT_SETTINGS_TAG, "Settings version mismatch"); + FURI_LOG_E(TAG, "Settings version mismatch"); } else { osKernelLock(); *bt_settings = settings; osKernelUnlock(); } } else { - FURI_LOG_E(BT_SETTINGS_TAG, "Settings load failed"); + FURI_LOG_E(TAG, "Settings load failed"); } return file_loaded; } @@ -41,7 +41,7 @@ bool bt_settings_save(BtSettings* bt_settings) { FileWorker* file_worker = file_worker_alloc(true); if(file_worker_open(file_worker, BT_SETTINGS_PATH, FSAM_WRITE, FSOM_OPEN_ALWAYS)) { if(file_worker_write(file_worker, bt_settings, sizeof(BtSettings))) { - FURI_LOG_I(BT_SETTINGS_TAG, "Settings saved to \"%s\"", BT_SETTINGS_PATH); + FURI_LOG_I(TAG, "Settings saved to \"%s\"", BT_SETTINGS_PATH); result = true; } } diff --git a/applications/debug_tools/bad_usb.c b/applications/debug_tools/bad_usb.c index ad20e26e..c5fc0f24 100644 --- a/applications/debug_tools/bad_usb.c +++ b/applications/debug_tools/bad_usb.c @@ -6,6 +6,9 @@ #include #include +#define TAG "BadUsb" +#define WORKER_TAG TAG "Worker" + typedef enum { EventTypeInput, EventTypeWorkerState, @@ -191,7 +194,7 @@ static bool ducky_parse_line(string_t line, BadUsbParams* app) { static void badusb_worker(void* context) { BadUsbParams* app = context; - FURI_LOG_I("BadUSB worker", "Init"); + FURI_LOG_I(WORKER_TAG, "Init"); File* script_file = storage_file_alloc(furi_record_open("storage")); BadUsbEvent evt; string_t line; @@ -203,7 +206,7 @@ static void badusb_worker(void* context) { uint32_t flags = osThreadFlagsWait(WorkerCmdStart | WorkerCmdStop, osFlagsWaitAny, osWaitForever); if(flags & WorkerCmdStart) { - FURI_LOG_I("BadUSB worker", "Start"); + FURI_LOG_I(WORKER_TAG, "Start"); do { ret = storage_file_read(script_file, buffer, 16); for(uint16_t i = 0; i < ret; i++) { @@ -211,7 +214,7 @@ static void badusb_worker(void* context) { line_cnt++; if(ducky_parse_line(line, app) == false) { ret = 0; - FURI_LOG_E("BadUSB worker", "Unknown command at line %lu", line_cnt); + FURI_LOG_E(WORKER_TAG, "Unknown command at line %lu", line_cnt); evt.type = EventTypeWorkerState; evt.worker.state = WorkerStateScriptError; evt.worker.line = line_cnt; @@ -231,7 +234,7 @@ static void badusb_worker(void* context) { } while(ret > 0); } } else { - FURI_LOG_E("BadUSB worker", "Script file open error"); + FURI_LOG_E(WORKER_TAG, "Script file open error"); evt.type = EventTypeWorkerState; evt.worker.state = WorkerStateNoFile; osMessageQueuePut(app->event_queue, &evt, 0, osWaitForever); @@ -243,7 +246,7 @@ static void badusb_worker(void* context) { storage_file_close(script_file); storage_file_free(script_file); - FURI_LOG_I("BadUSB worker", "End"); + FURI_LOG_I(WORKER_TAG, "End"); evt.type = EventTypeWorkerState; evt.worker.state = WorkerStateDone; osMessageQueuePut(app->event_queue, &evt, 0, osWaitForever); @@ -324,7 +327,7 @@ int32_t bad_usb_app(void* p) { } } } else if(event.type == EventTypeWorkerState) { - FURI_LOG_I("BadUSB app", "ev: %d", event.worker.state); + FURI_LOG_I(TAG, "ev: %d", event.worker.state); if(event.worker.state == WorkerStateDone) { worker_running = false; if(app_state == AppStateExit) diff --git a/applications/debug_tools/display_test/display_test.c b/applications/debug_tools/display_test/display_test.c index f2685a82..5a53562d 100644 --- a/applications/debug_tools/display_test/display_test.c +++ b/applications/debug_tools/display_test/display_test.c @@ -14,6 +14,8 @@ #include "view_display_test.h" +#define TAG "DisplayTest" + typedef struct { Gui* gui; ViewDispatcher* view_dispatcher; @@ -77,7 +79,7 @@ static uint32_t display_test_exit_callback(void* context) { static void display_test_reload_config(DisplayTest* instance) { FURI_LOG_I( - "DisplayTest", + TAG, "contrast: %d, regulation_ratio: %d, bias: %d", instance->config_contrast, instance->config_regulation_ratio, diff --git a/applications/debug_tools/keypad_test.c b/applications/debug_tools/keypad_test.c index e390ccd5..20f259aa 100644 --- a/applications/debug_tools/keypad_test.c +++ b/applications/debug_tools/keypad_test.c @@ -2,6 +2,8 @@ #include #include +#define TAG "KeypadTest" + typedef struct { bool press[5]; uint16_t up; @@ -80,7 +82,7 @@ int32_t keypad_test_app(void* p) { ValueMutex state_mutex; if(!init_mutex(&state_mutex, &_state, sizeof(KeypadTestState))) { - FURI_LOG_E("KeypadTest", "cannot create mutex"); + FURI_LOG_E(TAG, "cannot create mutex"); return 0; } @@ -101,7 +103,7 @@ int32_t keypad_test_app(void* p) { if(event_status == osOK) { if(event.type == EventTypeInput) { FURI_LOG_I( - "KeypadTest", + TAG, "key: %s type: %s", input_get_key_name(event.input.key), input_get_type_name(event.input.type)); diff --git a/applications/desktop/helpers/desktop_animation.c b/applications/desktop/helpers/desktop_animation.c index 07eaf631..f570b171 100644 --- a/applications/desktop/helpers/desktop_animation.c +++ b/applications/desktop/helpers/desktop_animation.c @@ -1,5 +1,7 @@ #include "desktop_animation.h" +#define TAG "DesktopAnimation" + static const Icon* idle_scenes[] = {&A_Wink_128x64, &A_WatchingTV_128x64}; const Icon* desktop_get_icon() { @@ -12,10 +14,10 @@ const Icon* desktop_get_icon() { DolphinStats stats = dolphin_stats(dolphin); float timediff = fabs(difftime(stats.timestamp, dolphin_state_timestamp())); - FURI_LOG_I("desktop-animation", "background change"); - FURI_LOG_I("desktop-animation", "icounter: %d", stats.icounter); - FURI_LOG_I("desktop-animation", "butthurt: %d", stats.butthurt); - FURI_LOG_I("desktop-animation", "time since deeed: %.0f", timediff); + FURI_LOG_I(TAG, "background change"); + FURI_LOG_I(TAG, "icounter: %d", stats.icounter); + FURI_LOG_I(TAG, "butthurt: %d", stats.butthurt); + FURI_LOG_I(TAG, "time since deeed: %.0f", timediff); #endif if((random() % 100) > 50) { // temp rnd selection diff --git a/applications/dialogs/view_holder.c b/applications/dialogs/view_holder.c index 2307bcd8..56d88001 100644 --- a/applications/dialogs/view_holder.c +++ b/applications/dialogs/view_holder.c @@ -1,6 +1,8 @@ #include "view-holder.h" #include +#define TAG "ViewHolder" + struct ViewHolder { View* view; ViewPort* view_port; @@ -125,7 +127,7 @@ static void view_holder_input_callback(InputEvent* event, void* context) { view_holder->ongoing_input &= ~key_bit; } else if(!(view_holder->ongoing_input & key_bit)) { FURI_LOG_W( - "ViewHolder", + TAG, "non-complementary input, discarding key: %s, type: %s", input_get_key_name(event->key), input_get_type_name(event->type)); diff --git a/applications/dolphin/dolphin.c b/applications/dolphin/dolphin.c index 1415f435..09bdb982 100644 --- a/applications/dolphin/dolphin.c +++ b/applications/dolphin/dolphin.c @@ -82,7 +82,7 @@ static void dolphin_check_butthurt(DolphinState* state) { float diff_time = difftime(dolphin_state_get_timestamp(state), dolphin_state_timestamp()); if((fabs(diff_time)) > DOLPHIN_TIMEGATE) { - FURI_LOG_I("dolphin-state", "Increasing butthurt"); + FURI_LOG_I("DolphinState", "Increasing butthurt"); dolphin_state_butthurted(state); } } diff --git a/applications/dolphin/helpers/dolphin_state.c b/applications/dolphin/helpers/dolphin_state.c index 379908c9..31066534 100644 --- a/applications/dolphin/helpers/dolphin_state.c +++ b/applications/dolphin/helpers/dolphin_state.c @@ -4,7 +4,7 @@ #include #include -#define DOLPHIN_STATE_TAG "DolphinState" +#define TAG "DolphinState" #define DOLPHIN_STATE_PATH "/int/dolphin.state" #define DOLPHIN_STATE_HEADER_MAGIC 0xD0 #define DOLPHIN_STATE_HEADER_VERSION 0x01 @@ -48,10 +48,10 @@ bool dolphin_state_save(DolphinState* dolphin_state) { DOLPHIN_STATE_HEADER_VERSION); if(result) { - FURI_LOG_I(DOLPHIN_STATE_TAG, "State saved"); + FURI_LOG_I(TAG, "State saved"); dolphin_state->dirty = false; } else { - FURI_LOG_E(DOLPHIN_STATE_TAG, "Failed to save state"); + FURI_LOG_E(TAG, "Failed to save state"); } return result; @@ -66,7 +66,7 @@ bool dolphin_state_load(DolphinState* dolphin_state) { DOLPHIN_STATE_HEADER_VERSION); if(!loaded) { - FURI_LOG_W(DOLPHIN_STATE_TAG, "Reset dolphin-state"); + FURI_LOG_W(TAG, "Reset dolphin-state"); memset(dolphin_state, 0, sizeof(*dolphin_state)); dolphin_state->dirty = true; } diff --git a/applications/gpio/usb_uart_bridge.c b/applications/gpio/usb_uart_bridge.c index ff787ea7..9b43f643 100644 --- a/applications/gpio/usb_uart_bridge.c +++ b/applications/gpio/usb_uart_bridge.c @@ -8,11 +8,12 @@ #define USB_UART_RX_BUF_SIZE (USB_CDC_PKT_LEN * 5) typedef enum { - WorkerEvtStop = (1 << 0), - WorkerEvtRxDone = (1 << 1), + WorkerEvtReserved = (1 << 0), // Reserved for StreamBuffer internal event + WorkerEvtStop = (1 << 1), + WorkerEvtRxDone = (1 << 2), - WorkerEvtTxStop = (1 << 2), - WorkerEvtCdcRx = (1 << 3), + WorkerEvtTxStop = (1 << 3), + WorkerEvtCdcRx = (1 << 4), } WorkerEvtFlags; #define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone) @@ -75,7 +76,7 @@ static int32_t usb_uart_worker(void* context) { usb_uart->usb_mutex = osMutexNew(NULL); usb_uart->tx_thread = furi_thread_alloc(); - furi_thread_set_name(usb_uart->tx_thread, "usb_uart_tx"); + furi_thread_set_name(usb_uart->tx_thread, "UsbUartTxWorker"); furi_thread_set_stack_size(usb_uart->tx_thread, 512); furi_thread_set_context(usb_uart->tx_thread, NULL); furi_thread_set_callback(usb_uart->tx_thread, usb_uart_tx_thread); @@ -191,7 +192,7 @@ void usb_uart_enable(UsbUartConfig* cfg) { usb_uart = furi_alloc(sizeof(UsbUartParams)); usb_uart->thread = furi_thread_alloc(); - furi_thread_set_name(usb_uart->thread, "usb_uart"); + furi_thread_set_name(usb_uart->thread, "UsbUartWorker"); furi_thread_set_stack_size(usb_uart->thread, 1024); furi_thread_set_context(usb_uart->thread, cfg); furi_thread_set_callback(usb_uart->thread, usb_uart_worker); diff --git a/applications/gui/gui.c b/applications/gui/gui.c index 46a515a0..ff872ab4 100644 --- a/applications/gui/gui.c +++ b/applications/gui/gui.c @@ -1,5 +1,7 @@ #include "gui_i.h" +#define TAG "GuiSrv" + ViewPort* gui_view_port_find_enabled(ViewPortArray_t array) { // Iterating backward ViewPortArray_it_t it; @@ -190,7 +192,7 @@ void gui_input(Gui* gui, InputEvent* input_event) { gui->ongoing_input |= key_bit; } else if(!(gui->ongoing_input & key_bit)) { FURI_LOG_D( - "Gui", + TAG, "non-complementary input, discarding key: %s type: %s, sequence: %p", input_get_key_name(input_event->key), input_get_type_name(input_event->type), @@ -212,7 +214,7 @@ void gui_input(Gui* gui, InputEvent* input_event) { view_port_input(view_port, input_event); } else if(gui->ongoing_input_view_port && input_event->type == InputTypeRelease) { FURI_LOG_D( - "Gui", + TAG, "ViewPort changed while key press %p -> %p. Sending key: %s, type: %s, sequence: %p to previous view port", gui->ongoing_input_view_port, view_port, @@ -222,7 +224,7 @@ void gui_input(Gui* gui, InputEvent* input_event) { view_port_input(gui->ongoing_input_view_port, input_event); } else { FURI_LOG_D( - "Gui", + TAG, "ViewPort changed while key press %p -> %p. Discarding key: %s, type: %s, sequence: %p", gui->ongoing_input_view_port, view_port, diff --git a/applications/gui/view_dispatcher.c b/applications/gui/view_dispatcher.c index e50c1809..f12cfe8b 100644 --- a/applications/gui/view_dispatcher.c +++ b/applications/gui/view_dispatcher.c @@ -1,5 +1,7 @@ #include "view_dispatcher_i.h" +#define TAG "ViewDispatcher" + ViewDispatcher* view_dispatcher_alloc() { ViewDispatcher* view_dispatcher = furi_alloc(sizeof(ViewDispatcher)); @@ -237,7 +239,7 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e view_dispatcher->ongoing_input &= ~key_bit; } else if(!(view_dispatcher->ongoing_input & key_bit)) { FURI_LOG_D( - "ViewDispatcher", + TAG, "non-complementary input, discarding key: %s, type: %s, sequence: %p", input_get_key_name(event->key), input_get_type_name(event->type), @@ -276,7 +278,7 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e } } else if(view_dispatcher->ongoing_input_view && event->type == InputTypeRelease) { FURI_LOG_D( - "ViewDispatcher", + TAG, "View changed while key press %p -> %p. Sending key: %s, type: %s, sequence: %p to previous view port", view_dispatcher->ongoing_input_view, view_dispatcher->current_view, diff --git a/applications/irda/irda-app-file-parser.cpp b/applications/irda/irda-app-file-parser.cpp index 3ab14fc0..b556fb6c 100644 --- a/applications/irda/irda-app-file-parser.cpp +++ b/applications/irda/irda-app-file-parser.cpp @@ -11,6 +11,8 @@ #include #include +#define TAG "IrdaFileParser" + bool IrdaAppFileParser::open_irda_file_read(const char* name) { std::string full_filename; if(name[0] != '/') @@ -154,11 +156,7 @@ std::unique_ptr if(!irda_is_protocol_valid((IrdaProtocol)protocol)) { size_t end_of_str = MIN(str.find_last_not_of(" \t\r\n") + 1, (size_t)30); FURI_LOG_E( - "IrdaFileParser", - "Unknown protocol(\'%.*s...\'): \'%s\'", - end_of_str, - str.c_str(), - protocol_name); + TAG, "Unknown protocol(\'%.*s...\'): \'%s\'", end_of_str, str.c_str(), protocol_name); return nullptr; } @@ -167,7 +165,7 @@ std::unique_ptr if(address != (address & address_mask)) { size_t end_of_str = MIN(str.find_last_not_of(" \t\r\n") + 1, (size_t)30); FURI_LOG_E( - "IrdaFileParser", + TAG, "Signal(\'%.*s...\'): address is too long (mask for this protocol is 0x%08X): 0x%X", end_of_str, str.c_str(), @@ -181,7 +179,7 @@ std::unique_ptr if(command != (command & command_mask)) { size_t end_of_str = MIN(str.find_last_not_of(" \t\r\n") + 1, (size_t)30); FURI_LOG_E( - "IrdaFileParser", + TAG, "Signal(\'%.*s...\'): command is too long (mask for this protocol is 0x%08X): 0x%X", end_of_str, str.c_str(), @@ -256,7 +254,7 @@ std::unique_ptr if((frequency < IRDA_MIN_FREQUENCY) || (frequency > IRDA_MAX_FREQUENCY)) { size_t end_of_str = MIN(string.find_last_not_of(" \t\r\n") + 1, (size_t)30); FURI_LOG_E( - "IrdaFileParser", + TAG, "RAW signal(\'%.*s...\'): frequency is out of bounds (%ld-%ld): %ld", end_of_str, string.c_str(), @@ -269,7 +267,7 @@ std::unique_ptr if((duty_cycle == 0) || (duty_cycle > 100)) { size_t end_of_str = MIN(string.find_last_not_of(" \t\r\n") + 1, (size_t)30); FURI_LOG_E( - "IrdaFileParser", + TAG, "RAW signal(\'%.*s...\'): duty cycle is out of bounds (0-100): %ld", end_of_str, string.c_str(), @@ -283,8 +281,7 @@ std::unique_ptr if(last_valid_ch != std::string_view::npos) { str.remove_suffix(str.size() - last_valid_ch - 1); } else { - FURI_LOG_E( - "IrdaFileParser", "RAW signal(\'%.*s\'): no timings", header_len, string.c_str()); + FURI_LOG_E(TAG, "RAW signal(\'%.*s\'): no timings", header_len, string.c_str()); return nullptr; } @@ -303,7 +300,7 @@ std::unique_ptr parsed = std::sscanf(str.data(), "%9s", buf); if(parsed != 1) { FURI_LOG_E( - "IrdaFileParser", + TAG, "RAW signal(\'%.*s...\'): failed on timing[%ld] \'%*s\'", header_len, string.c_str(), @@ -318,7 +315,7 @@ std::unique_ptr int value = atoi(buf); if(value <= 0) { FURI_LOG_E( - "IrdaFileParser", + TAG, "RAW signal(\'%.*s...\'): failed on timing[%ld] \'%s\'", header_len, string.c_str(), @@ -330,7 +327,7 @@ std::unique_ptr if(raw_signal.timings_cnt >= max_raw_timings_in_signal) { FURI_LOG_E( - "IrdaFileParser", + TAG, "RAW signal(\'%.*s...\'): too much timings (max %ld)", header_len, string.c_str(), diff --git a/applications/loader/loader.c b/applications/loader/loader.c index 574db256..98ce42b1 100644 --- a/applications/loader/loader.c +++ b/applications/loader/loader.c @@ -1,6 +1,8 @@ #include "loader/loader.h" #include "loader_i.h" +#define TAG "LoaderSrv" + #define LOADER_THREAD_FLAG_SHOW_MENU (1 << 0) #define LOADER_THREAD_FLAG_ALL (LOADER_THREAD_FLAG_SHOW_MENU) @@ -15,15 +17,13 @@ static void loader_menu_callback(void* _ctx, uint32_t index) { if(!loader_lock(loader_instance)) return; if(furi_thread_get_state(loader_instance->thread) != FuriThreadStateStopped) { - FURI_LOG_E( - LOADER_LOG_TAG, "Can't start app. %s is running", loader_instance->current_app->name); + FURI_LOG_E(TAG, "Can't start app. %s is running", loader_instance->current_app->name); return; } furi_hal_power_insomnia_enter(); loader_instance->current_app = flipper_app; - FURI_LOG_I( - LOADER_LOG_TAG, "Starting furi application: %s", loader_instance->current_app->name); + FURI_LOG_I(TAG, "Starting furi application: %s", loader_instance->current_app->name); furi_thread_set_name(loader_instance->thread, flipper_app->name); furi_thread_set_stack_size(loader_instance->thread, flipper_app->stack_size); furi_thread_set_context(loader_instance->thread, NULL); @@ -79,14 +79,14 @@ LoaderStatus loader_start(Loader* instance, const char* name, const char* args) } if(!flipper_app) { - FURI_LOG_E(LOADER_LOG_TAG, "Can't find application with name %s", name); + FURI_LOG_E(TAG, "Can't find application with name %s", name); return LoaderStatusErrorUnknownApp; } bool locked = loader_lock(instance); if(!locked || (furi_thread_get_state(instance->thread) != FuriThreadStateStopped)) { - FURI_LOG_E(LOADER_LOG_TAG, "Can't start app. %s is running", instance->current_app->name); + FURI_LOG_E(TAG, "Can't start app. %s is running", instance->current_app->name); /* no need to call loader_unlock() - it is called as soon as application stops */ return LoaderStatusErrorAppStarted; } @@ -97,10 +97,10 @@ LoaderStatus loader_start(Loader* instance, const char* name, const char* args) string_set_str(instance->args, args); string_strim(instance->args); thread_args = (void*)string_get_cstr(instance->args); - FURI_LOG_I(LOADER_LOG_TAG, "Start %s app with args: %s", name, args); + FURI_LOG_I(TAG, "Start %s app with args: %s", name, args); } else { string_clean(instance->args); - FURI_LOG_I(LOADER_LOG_TAG, "Start %s app with no args", name); + FURI_LOG_I(TAG, "Start %s app with no args", name); } furi_thread_set_name(instance->thread, flipper_app->name); @@ -155,7 +155,7 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con delay(20); int heap_diff = instance->free_heap_size - memmgr_get_free_heap(); FURI_LOG_I( - LOADER_LOG_TAG, + TAG, "Application thread stopped. Heap allocation balance: %d. Thread allocation balance: %d.", heap_diff, furi_thread_get_heap_size(instance->thread)); @@ -266,7 +266,7 @@ static void loader_add_cli_command(FlipperApplication* app) { } static void loader_build_menu() { - FURI_LOG_I(LOADER_LOG_TAG, "Building main menu"); + FURI_LOG_I(TAG, "Building main menu"); size_t i; for(i = 0; i < FLIPPER_APPS_COUNT; i++) { loader_add_cli_command((FlipperApplication*)&FLIPPER_APPS[i]); @@ -300,7 +300,7 @@ static void loader_build_menu() { loader_submenu_callback, (void*)LoaderMenuViewSettings); - FURI_LOG_I(LOADER_LOG_TAG, "Building plugins menu"); + FURI_LOG_I(TAG, "Building plugins menu"); for(i = 0; i < FLIPPER_PLUGINS_COUNT; i++) { loader_add_cli_command((FlipperApplication*)&FLIPPER_PLUGINS[i]); submenu_add_item( @@ -311,7 +311,7 @@ static void loader_build_menu() { (void*)&FLIPPER_PLUGINS[i]); } - FURI_LOG_I(LOADER_LOG_TAG, "Building debug menu"); + FURI_LOG_I(TAG, "Building debug menu"); for(i = 0; i < FLIPPER_DEBUG_APPS_COUNT; i++) { loader_add_cli_command((FlipperApplication*)&FLIPPER_DEBUG_APPS[i]); submenu_add_item( @@ -322,7 +322,7 @@ static void loader_build_menu() { (void*)&FLIPPER_DEBUG_APPS[i]); } - FURI_LOG_I(LOADER_LOG_TAG, "Building settings menu"); + FURI_LOG_I(TAG, "Building settings menu"); for(i = 0; i < FLIPPER_SETTINGS_APPS_COUNT; i++) { submenu_add_item( loader_instance->settings_menu, @@ -339,7 +339,7 @@ void loader_show_menu() { } int32_t loader_srv(void* p) { - FURI_LOG_I(LOADER_LOG_TAG, "Starting"); + FURI_LOG_I(TAG, "Starting"); loader_instance = loader_alloc(); @@ -350,7 +350,7 @@ int32_t loader_srv(void* p) { FLIPPER_ON_SYSTEM_START[i](); } - FURI_LOG_I(LOADER_LOG_TAG, "Started"); + FURI_LOG_I(TAG, "Started"); furi_record_create("loader", loader_instance); diff --git a/applications/loader/loader_i.h b/applications/loader/loader_i.h index 8d44911f..08c9ac09 100644 --- a/applications/loader/loader_i.h +++ b/applications/loader/loader_i.h @@ -12,8 +12,6 @@ #include #include -#define LOADER_LOG_TAG "loader" - struct Loader { osThreadId_t loader_thread; FuriThread* thread; diff --git a/applications/nfc/helpers/nfc_emv_parser.c b/applications/nfc/helpers/nfc_emv_parser.c index b84d35c3..54c6c203 100755 --- a/applications/nfc/helpers/nfc_emv_parser.c +++ b/applications/nfc/helpers/nfc_emv_parser.c @@ -1,49 +1,80 @@ #include "nfc_emv_parser.h" +#include -#include +static const char* nfc_resources_header = "Flipper EMV resources"; +static const uint32_t nfc_resources_file_version = 1; -static bool - nfc_emv_parser_get_value(const char* file_path, string_t key, char delimiter, string_t value) { - bool found = false; - FileWorker* file_worker = file_worker_alloc(true); +static bool nfc_emv_parser_search_data( + Storage* storage, + const char* file_name, + string_t key, + string_t data) { + bool parsed = false; + FlipperFile* file = flipper_file_alloc(storage); + string_t temp_str; + string_init(temp_str); - if(file_worker_open(file_worker, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) { - if(file_worker_get_value_from_key(file_worker, key, delimiter, value)) { - found = true; - } - } + do { + // Open file + if(!flipper_file_open_existing(file, file_name)) break; + // Read file header and version + uint32_t version = 0; + if(!flipper_file_read_header(file, temp_str, &version)) break; + if(string_cmp_str(temp_str, nfc_resources_header) || + (version != nfc_resources_file_version)) + break; + if(!flipper_file_read_string(file, string_get_cstr(key), data)) break; + parsed = true; + } while(false); - file_worker_close(file_worker); - file_worker_free(file_worker); - return found; + string_clear(temp_str); + flipper_file_free(file); + return parsed; } -bool nfc_emv_parser_get_aid_name(uint8_t* aid, uint8_t aid_len, string_t aid_name) { - bool result = false; +bool nfc_emv_parser_get_aid_name( + Storage* storage, + uint8_t* aid, + uint8_t aid_len, + string_t aid_name) { + furi_assert(storage); + bool parsed = false; string_t key; string_init(key); for(uint8_t i = 0; i < aid_len; i++) { string_cat_printf(key, "%02X", aid[i]); } - result = nfc_emv_parser_get_value("/ext/nfc/emv/aid.nfc", key, ' ', aid_name); + if(nfc_emv_parser_search_data(storage, "/ext/nfc/emv/aid.nfc", key, aid_name)) { + parsed = true; + } string_clear(key); - return result; + return parsed; } -bool nfc_emv_parser_get_country_name(uint16_t country_code, string_t country_name) { - bool result = false; +bool nfc_emv_parser_get_country_name( + Storage* storage, + uint16_t country_code, + string_t country_name) { + bool parsed = false; string_t key; string_init_printf(key, "%04X", country_code); - result = nfc_emv_parser_get_value("/ext/nfc/emv/country_code.nfc", key, ' ', country_name); + if(nfc_emv_parser_search_data(storage, "/ext/nfc/emv/country_code.nfc", key, country_name)) { + parsed = true; + } string_clear(key); - return result; + return parsed; } -bool nfc_emv_parser_get_currency_name(uint16_t currency_code, string_t currency_name) { - bool result = false; +bool nfc_emv_parser_get_currency_name( + Storage* storage, + uint16_t currency_code, + string_t currency_name) { + bool parsed = false; string_t key; string_init_printf(key, "%04X", currency_code); - result = nfc_emv_parser_get_value("/ext/nfc/emv/currency_code.nfc", key, ' ', currency_name); + if(nfc_emv_parser_search_data(storage, "/ext/nfc/emv/currency_code.nfc", key, currency_name)) { + parsed = true; + } string_clear(key); - return result; + return parsed; } diff --git a/applications/nfc/helpers/nfc_emv_parser.h b/applications/nfc/helpers/nfc_emv_parser.h index b81a06ee..5948ed34 100755 --- a/applications/nfc/helpers/nfc_emv_parser.h +++ b/applications/nfc/helpers/nfc_emv_parser.h @@ -3,25 +3,39 @@ #include #include #include +#include /** Get EMV application name by number + * @param storage Storage instance * @param aid - AID number array * @param aid_len - AID length * @param aid_name - string to keep AID name * @return - true if AID found, false otherwies */ -bool nfc_emv_parser_get_aid_name(uint8_t* aid, uint8_t aid_len, string_t aid_name); +bool nfc_emv_parser_get_aid_name( + Storage* storage, + uint8_t* aid, + uint8_t aid_len, + string_t aid_name); /** Get country name by country code + * @param storage Storage instance * @param country_code - ISO 3166 country code * @param country_name - string to keep country name * @return - true if country found, false otherwies */ -bool nfc_emv_parser_get_country_name(uint16_t country_code, string_t country_name); +bool nfc_emv_parser_get_country_name( + Storage* storage, + uint16_t country_code, + string_t country_name); /** Get currency name by currency code + * @param storage Storage instance * @param currency_code - ISO 3166 currency code * @param currency_name - string to keep currency name * @return - true if currency found, false otherwies */ -bool nfc_emv_parser_get_currency_name(uint16_t currency_code, string_t currency_name); +bool nfc_emv_parser_get_currency_name( + Storage* storage, + uint16_t currency_code, + string_t currency_name); diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index 5bf788b9..a29a6d19 100755 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -31,6 +31,9 @@ Nfc* nfc_alloc() { view_dispatcher_set_navigation_event_callback(nfc->view_dispatcher, nfc_back_event_callback); view_dispatcher_set_tick_event_callback(nfc->view_dispatcher, nfc_tick_event_callback, 100); + // Nfc device + nfc->dev = nfc_device_alloc(); + // Open GUI record nfc->gui = furi_record_open("gui"); view_dispatcher_attach_to_gui(nfc->view_dispatcher, nfc->gui, ViewDispatcherTypeFullscreen); @@ -82,6 +85,9 @@ Nfc* nfc_alloc() { void nfc_free(Nfc* nfc) { furi_assert(nfc); + // Nfc device + nfc_device_free(nfc->dev); + // Submenu view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewMenu); submenu_free(nfc->submenu); @@ -154,8 +160,12 @@ int32_t nfc_app(void* p) { char* args = p; // Check argument and run corresponding scene - if((*args != '\0') && nfc_device_load(&nfc->dev, p)) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); + if((*args != '\0') && nfc_device_load(nfc->dev, p)) { + if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl); + } else { + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); + } } else { scene_manager_next_scene(nfc->scene_manager, NfcSceneStart); } diff --git a/applications/nfc/nfc_device.c b/applications/nfc/nfc_device.c index 24fd8e40..17a261f2 100755 --- a/applications/nfc/nfc_device.c +++ b/applications/nfc/nfc_device.c @@ -1,45 +1,38 @@ -#include "nfc_device_i.h" +#include "nfc_device.h" -#include #include -#include - -#define NFC_DEVICE_MAX_DATA_LEN 14 +#include static const char* nfc_app_folder = "/any/nfc"; static const char* nfc_app_extension = ".nfc"; static const char* nfc_app_shadow_extension = ".shd"; +static const char* nfc_file_header = "Flipper NFC device"; +static const uint32_t nfc_file_version = 2; -static bool nfc_device_read_hex(string_t str, uint8_t* buff, uint16_t len, uint8_t delim_len) { - string_strim(str); - uint8_t nibble_high = 0; - uint8_t nibble_low = 0; - bool parsed = true; - - for(uint16_t i = 0; i < len; i++) { - if(hex_char_to_hex_nibble(string_get_char(str, 0), &nibble_high) && - hex_char_to_hex_nibble(string_get_char(str, 1), &nibble_low)) { - buff[i] = (nibble_high << 4) | nibble_low; - string_right(str, delim_len + 2); - } else { - parsed = false; - break; - } - } - return parsed; +NfcDevice* nfc_device_alloc() { + NfcDevice* nfc_dev = furi_alloc(sizeof(NfcDevice)); + nfc_dev->storage = furi_record_open("storage"); + nfc_dev->dialogs = furi_record_open("dialogs"); + return nfc_dev; } -uint16_t nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string) { +void nfc_device_free(NfcDevice* nfc_dev) { + furi_assert(nfc_dev); + furi_record_close("storage"); + furi_record_close("dialogs"); + free(nfc_dev); +} + +void nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string) { if(dev->format == NfcDeviceSaveFormatUid) { - string_set_str(format_string, "UID\n"); + string_set_str(format_string, "UID"); } else if(dev->format == NfcDeviceSaveFormatBankCard) { - string_set_str(format_string, "Bank card\n"); + string_set_str(format_string, "Bank card"); } else if(dev->format == NfcDeviceSaveFormatMifareUl) { - string_set_str(format_string, "Mifare Ultralight\n"); + string_set_str(format_string, "Mifare Ultralight"); } else { - string_set_str(format_string, "Unknown\n"); + string_set_str(format_string, "Unknown"); } - return string_size(format_string); } bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string) { @@ -59,228 +52,166 @@ bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string) { return false; } -uint16_t nfc_device_prepare_uid_string(NfcDevice* dev, string_t uid_string) { - NfcDeviceCommonData* uid_data = &dev->dev_data.nfc_data; - string_printf(uid_string, "UID len: %02X UID: ", dev->dev_data.nfc_data.uid_len); - for(uint8_t i = 0; i < uid_data->uid_len; i++) { - string_cat_printf(uid_string, "%02X ", uid_data->uid[i]); - } - string_cat_printf( - uid_string, - "ATQA: %02X %02X SAK: %02X\n", - uid_data->atqa[0], - uid_data->atqa[1], - uid_data->sak); - return string_size(uid_string); -} - -bool nfc_device_parse_uid_string(NfcDevice* dev, string_t uid_string) { - NfcDeviceCommonData* uid_data = &dev->dev_data.nfc_data; - bool parsed = false; - - do { - // strlen("UID len: ") = 9 - string_right(uid_string, 9); - if(!nfc_device_read_hex(uid_string, &uid_data->uid_len, 1, 1)) { - break; - } - // strlen("UID: ") = 5 - string_right(uid_string, 5); - if(!nfc_device_read_hex(uid_string, uid_data->uid, uid_data->uid_len, 1)) { - break; - } - // strlen("ATQA: ") = 6 - string_right(uid_string, 6); - if(!nfc_device_read_hex(uid_string, uid_data->atqa, 2, 1)) { - break; - } - // strlen("SAK: ") = 5 - string_right(uid_string, 5); - if(!nfc_device_read_hex(uid_string, &uid_data->sak, 1, 1)) { - break; - } - parsed = true; - } while(0); - - return parsed; -} - -uint16_t nfc_device_prepare_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string) { +static bool nfc_device_save_mifare_ul_data(FlipperFile* file, NfcDevice* dev) { + bool saved = false; MifareUlData* data = &dev->dev_data.mf_ul_data; - string_printf(mifare_ul_string, "Signature:"); - for(uint8_t i = 0; i < sizeof(data->signature); i++) { - string_cat_printf(mifare_ul_string, " %02X", data->signature[i]); - } - string_cat_printf(mifare_ul_string, "\nVersion:"); - uint8_t* version = (uint8_t*)&data->version; - for(uint8_t i = 0; i < sizeof(data->version); i++) { - string_cat_printf(mifare_ul_string, " %02X", version[i]); - } - for(uint8_t i = 0; i < 3; i++) { - string_cat_printf( - mifare_ul_string, - "\nCounter %d: %lu Tearing flag %d: %02X", - i, - data->counter[i], - i, - data->tearing[i]); - } - string_cat_printf(mifare_ul_string, "\nData size: %d\n", data->data_size); - for(uint16_t i = 0; i < data->data_size; i += 4) { - string_cat_printf( - mifare_ul_string, - "%02X %02X %02X %02X\n", - data->data[i], - data->data[i + 1], - data->data[i + 2], - data->data[i + 3]); - } - return string_size(mifare_ul_string); -} - -bool nfc_device_parse_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string) { - MifareUlData* data = &dev->dev_data.mf_ul_data; - uint16_t tearing_tmp = 0; - uint16_t cnt_num = 0; - size_t ws = 0; - int res = 0; - bool parsed = false; + string_t temp_str; + string_init(temp_str); + // Save Mifare Ultralight specific data do { - // strlen("Signature: ") = 11 - string_right(mifare_ul_string, 11); - if(!nfc_device_read_hex(mifare_ul_string, data->signature, sizeof(data->signature), 1)) { + if(!flipper_file_write_comment_cstr(file, "Mifare Ultralight specific data")) break; + if(!flipper_file_write_hex(file, "Signature", data->signature, sizeof(data->signature))) break; - } - // strlen("Version: ") = 9 - string_right(mifare_ul_string, 9); - if(!nfc_device_read_hex( - mifare_ul_string, (uint8_t*)&data->version, sizeof(data->version), 1)) { + if(!flipper_file_write_hex( + file, "Mifare version", (uint8_t*)&data->version, sizeof(data->version))) break; - } - string_strim(mifare_ul_string); - // Read counters and tearing flags + // Write conters and tearing flags data + bool counters_saved = true; for(uint8_t i = 0; i < 3; i++) { - res = sscanf( - string_get_cstr(mifare_ul_string), - "Counter %hX: %lu Tearing flag %hX: %02hX", - &cnt_num, - &data->counter[i], - &cnt_num, - &tearing_tmp); - if(res != 4) { + string_printf(temp_str, "Counter %d", i); + if(!flipper_file_write_uint32(file, string_get_cstr(temp_str), &data->counter[i], 1)) { + counters_saved = false; + break; + } + string_printf(temp_str, "Tearing %d", i); + if(!flipper_file_write_hex(file, string_get_cstr(temp_str), &data->tearing[i], 1)) { + counters_saved = false; break; } - data->tearing[i] = tearing_tmp; - ws = string_search_char(mifare_ul_string, '\n'); - string_right(mifare_ul_string, ws + 1); } - // Read data size - res = sscanf(string_get_cstr(mifare_ul_string), "Data size: %hu", &data->data_size); - if(res != 1) { - break; - } - ws = string_search_char(mifare_ul_string, '\n'); - string_right(mifare_ul_string, ws + 1); - // Read data + if(!counters_saved) break; + // Write pages data + uint32_t pages_total = data->data_size / 4; + if(!flipper_file_write_uint32(file, "Pages total", &pages_total, 1)) break; + bool pages_saved = true; for(uint16_t i = 0; i < data->data_size; i += 4) { - if(!nfc_device_read_hex(mifare_ul_string, &data->data[i], 4, 1)) { + string_printf(temp_str, "Page %d", i / 4); + if(!flipper_file_write_hex(file, string_get_cstr(temp_str), &data->data[i], 4)) { + pages_saved = false; break; } } - parsed = true; - } while(0); + if(!pages_saved) break; + saved = true; + } while(false); + string_clear(temp_str); + return saved; +} + +bool nfc_device_load_mifare_ul_data(FlipperFile* file, NfcDevice* dev) { + bool parsed = false; + MifareUlData* data = &dev->dev_data.mf_ul_data; + string_t temp_str; + string_init(temp_str); + + do { + // Read signature + if(!flipper_file_read_hex(file, "Signature", data->signature, sizeof(data->signature))) + break; + // Read Mifare version + if(!flipper_file_read_hex( + file, "Mifare version", (uint8_t*)&data->version, sizeof(data->version))) + break; + // Read counters and tearing flags + bool counters_parsed = true; + for(uint8_t i = 0; i < 3; i++) { + string_printf(temp_str, "Counter %d", i); + if(!flipper_file_read_uint32(file, string_get_cstr(temp_str), &data->counter[i], 1)) { + counters_parsed = false; + break; + } + string_printf(temp_str, "Tearing %d", i); + if(!flipper_file_read_hex(file, string_get_cstr(temp_str), &data->tearing[i], 1)) { + counters_parsed = false; + break; + } + } + if(!counters_parsed) break; + // Read pages + uint32_t pages = 0; + if(!flipper_file_read_uint32(file, "Pages total", &pages, 1)) break; + data->data_size = pages * 4; + bool pages_parsed = true; + for(uint16_t i = 0; i < pages; i++) { + string_printf(temp_str, "Page %d", i); + if(!flipper_file_read_hex(file, string_get_cstr(temp_str), &data->data[i * 4], 4)) { + pages_parsed = false; + break; + } + } + if(!pages_parsed) break; + parsed = true; + } while(false); + + string_clear(temp_str); return parsed; } -uint16_t nfc_device_prepare_bank_card_string(NfcDevice* dev, string_t bank_card_string) { +static bool nfc_device_save_bank_card_data(FlipperFile* file, NfcDevice* dev) { + bool saved = false; NfcEmvData* data = &dev->dev_data.emv_data; - string_printf(bank_card_string, "AID len: %d, AID:", data->aid_len); - for(uint8_t i = 0; i < data->aid_len; i++) { - string_cat_printf(bank_card_string, " %02X", data->aid[i]); - } - string_cat_printf( - bank_card_string, "\nName: %s\nNumber len: %d\nNumber:", data->name, data->number_len); - for(uint8_t i = 0; i < data->number_len; i++) { - string_cat_printf(bank_card_string, " %02X", data->number[i]); - } - if(data->exp_mon) { - string_cat_printf( - bank_card_string, "\nExp date: %02X/%02X", data->exp_mon, data->exp_year); - } - if(data->country_code) { - string_cat_printf(bank_card_string, "\nCountry code: %04X", data->country_code); - } - if(data->currency_code) { - string_cat_printf(bank_card_string, "\nCurrency code: %04X", data->currency_code); - } - return string_size(bank_card_string); -} - -bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string) { - NfcEmvData* data = &dev->dev_data.emv_data; - bool parsed = false; - int res = 0; - uint8_t code[2] = {}; - memset(data, 0, sizeof(NfcEmvData)); + uint32_t data_temp = 0; do { - res = sscanf(string_get_cstr(bank_card_string), "AID len: %hu", &data->aid_len); - if(res != 1) { - break; + // Write Bank card specific data + if(!flipper_file_write_comment_cstr(file, "Bank card specific data")) break; + if(!flipper_file_write_hex(file, "AID", data->aid, data->aid_len)) break; + if(!flipper_file_write_string_cstr(file, "Name", data->name)) break; + if(!flipper_file_write_hex(file, "Number", data->number, data->number_len)) break; + if(data->exp_mon) { + uint8_t exp_data[2] = {data->exp_mon, data->exp_year}; + if(!flipper_file_write_hex(file, "Exp data", exp_data, sizeof(exp_data))) break; } - // strlen("AID len: ") = 9 - string_right(bank_card_string, 9); - size_t ws = string_search_char(bank_card_string, ':'); - string_right(bank_card_string, ws + 1); - if(!nfc_device_read_hex(bank_card_string, data->aid, data->aid_len, 1)) { - break; + if(data->country_code) { + data_temp = data->country_code; + if(!flipper_file_write_uint32(file, "Country code", &data_temp, 1)) break; } - res = sscanf(string_get_cstr(bank_card_string), "Name: %s\n", data->name); - if(res != 1) { - break; + if(data->currency_code) { + data_temp = data->currency_code; + if(!flipper_file_write_uint32(file, "Currency code", &data_temp, 1)) break; } - ws = string_search_char(bank_card_string, '\n'); - string_right(bank_card_string, ws + 1); - res = sscanf(string_get_cstr(bank_card_string), "Number len: %hhu", &data->number_len); - if(res != 1) { - break; - } - ws = string_search_char(bank_card_string, '\n'); - string_right(bank_card_string, ws + 1); - // strlen("Number: ") = 8 - string_right(bank_card_string, 8); - if(!nfc_device_read_hex(bank_card_string, data->number, data->number_len, 1)) { - break; - } - parsed = true; - // Check expiration date presence - ws = string_search_str(bank_card_string, "Exp date: "); - if(ws != STRING_FAILURE) { - // strlen("Exp date: ") = 10 - string_right(bank_card_string, 10); - nfc_device_read_hex(bank_card_string, &data->exp_mon, 1, 1); - nfc_device_read_hex(bank_card_string, &data->exp_year, 1, 1); - } - // Check country code presence - ws = string_search_str(bank_card_string, "Country code: "); - if(ws != STRING_FAILURE) { - // strlen("Country code: ") = 14 - string_right(bank_card_string, 14); - nfc_device_read_hex(bank_card_string, code, 2, 0); - data->country_code = code[0] << 8 | code[1]; - } - // Check currency code presence - ws = string_search_str(bank_card_string, "Currency code: "); - if(ws != STRING_FAILURE) { - // strlen("Currency code: ") = 15 - string_right(bank_card_string, 15); - nfc_device_read_hex(bank_card_string, code, 2, 0); - data->currency_code = code[0] << 8 | code[1]; - } - } while(0); + saved = true; + } while(false); + return saved; +} + +bool nfc_device_load_bank_card_data(FlipperFile* file, NfcDevice* dev) { + bool parsed = false; + NfcEmvData* data = &dev->dev_data.emv_data; + memset(data, 0, sizeof(NfcEmvData)); + uint32_t data_cnt = 0; + string_t temp_str; + string_init(temp_str); + + do { + // Load essential data + if(!flipper_file_get_value_count(file, "AID", &data_cnt)) break; + data->aid_len = data_cnt; + if(!flipper_file_read_hex(file, "AID", data->aid, data->aid_len)) break; + if(!flipper_file_read_string(file, "Name", temp_str)) break; + strlcpy(data->name, string_get_cstr(temp_str), sizeof(data->name)); + if(!flipper_file_get_value_count(file, "Number", &data_cnt)) break; + data->number_len = data_cnt; + if(!flipper_file_read_hex(file, "Number", data->number, data->number_len)) break; + parsed = true; + // Load optional data + uint8_t exp_data[2] = {}; + if(flipper_file_read_hex(file, "Exp data", exp_data, 2)) { + data->exp_mon = exp_data[0]; + data->exp_year = exp_data[1]; + } + if(flipper_file_read_uint32(file, "Country code", &data_cnt, 1)) { + data->country_code = data_cnt; + } + if(flipper_file_read_uint32(file, "Currency code", &data_cnt, 1)) { + data->currency_code = data_cnt; + } + } while(false); + + string_clear(temp_str); return parsed; } @@ -297,58 +228,49 @@ static bool nfc_device_save_file( const char* extension) { furi_assert(dev); - FileWorker* file_worker = file_worker_alloc(false); - string_t dev_file_name; - string_init(dev_file_name); + bool saved = false; + FlipperFile* file = flipper_file_alloc(dev->storage); + NfcDeviceCommonData* data = &dev->dev_data.nfc_data; string_t temp_str; string_init(temp_str); - uint16_t string_len = 0; do { // Create nfc directory if necessary - if(!file_worker_mkdir(file_worker, nfc_app_folder)) { - break; - }; + if(!storage_simply_mkdir(dev->storage, nfc_app_folder)) break; // First remove nfc device file if it was saved - string_printf(dev_file_name, "%s/%s%s", folder, dev_name, extension); - if(!file_worker_remove(file_worker, string_get_cstr(dev_file_name))) { - break; - }; + string_printf(temp_str, "%s/%s%s", folder, dev_name, extension); // Open file - if(!file_worker_open( - file_worker, string_get_cstr(dev_file_name), FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + if(!flipper_file_open_always(file, string_get_cstr(temp_str))) break; + // Write header + if(!flipper_file_write_header_cstr(file, nfc_file_header, nfc_file_version)) break; + // Write nfc device type + if(!flipper_file_write_comment_cstr( + file, "Nfc device type can be UID, Mifare Ultralight, Bank card")) break; - } - // Prepare and write format name on 1st line - string_len = nfc_device_prepare_format_string(dev, temp_str); - if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) { + nfc_device_prepare_format_string(dev, temp_str); + if(!flipper_file_write_string(file, "Device type", temp_str)) break; + // Write UID, ATQA, SAK + if(!flipper_file_write_comment_cstr(file, "UID, ATQA and SAK are common for all formats")) break; - } - // Prepare and write UID data on 2nd line - string_len = nfc_device_prepare_uid_string(dev, temp_str); - if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) { - break; - } + if(!flipper_file_write_hex(file, "UID", data->uid, data->uid_len)) break; + if(!flipper_file_write_hex(file, "ATQA", data->atqa, 2)) break; + if(!flipper_file_write_hex(file, "SAK", &data->sak, 1)) break; // Save more data if necessary if(dev->format == NfcDeviceSaveFormatMifareUl) { - string_len = nfc_device_prepare_mifare_ul_string(dev, temp_str); - if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) { - break; - } + if(!nfc_device_save_mifare_ul_data(file, dev)) break; } else if(dev->format == NfcDeviceSaveFormatBankCard) { - string_len = nfc_device_prepare_bank_card_string(dev, temp_str); - if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_len)) { - break; - } + if(!nfc_device_save_bank_card_data(file, dev)) break; } + saved = true; } while(0); + if(!saved) { + dialog_message_show_storage_error(dev->dialogs, "Can not save\nkey file"); + } string_clear(temp_str); - string_clear(dev_file_name); - file_worker_close(file_worker); - file_worker_free(file_worker); - - return true; + flipper_file_close(file); + flipper_file_free(file); + return saved; } bool nfc_device_save(NfcDevice* dev, const char* dev_name) { @@ -360,73 +282,64 @@ bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name) { return nfc_device_save_file(dev, dev_name, nfc_app_folder, nfc_app_shadow_extension); } -static bool nfc_device_load_data(FileWorker* file_worker, string_t path, NfcDevice* dev) { - string_t temp_string; - string_init(temp_string); +static bool nfc_device_load_data(NfcDevice* dev, string_t path) { bool parsed = false; + FlipperFile* file = flipper_file_alloc(dev->storage); + NfcDeviceCommonData* data = &dev->dev_data.nfc_data; + uint32_t data_cnt = 0; + string_t temp_str; + string_init(temp_str); + bool depricated_version = false; do { // Check existance of shadow file size_t ext_start = string_search_str(path, nfc_app_extension); - string_set_n(temp_string, path, 0, ext_start); - string_cat_printf(temp_string, "%s", nfc_app_shadow_extension); - if(!file_worker_is_file_exist( - file_worker, string_get_cstr(temp_string), &dev->shadow_file_exist)) { - break; - } + string_set_n(temp_str, path, 0, ext_start); + string_cat_printf(temp_str, "%s", nfc_app_shadow_extension); + dev->shadow_file_exist = + storage_common_stat(dev->storage, string_get_cstr(temp_str), NULL) == FSE_OK; // Open shadow file if it exists. If not - open original if(dev->shadow_file_exist) { - if(!file_worker_open( - file_worker, string_get_cstr(temp_string), FSAM_READ, FSOM_OPEN_EXISTING)) { - break; - } + if(!flipper_file_open_existing(file, string_get_cstr(temp_str))) break; } else { - if(!file_worker_open( - file_worker, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { - break; - } + if(!flipper_file_open_existing(file, string_get_cstr(path))) break; } - - // Read and parse format from 1st line - if(!file_worker_read_until(file_worker, temp_string, '\n')) { - break; - } - if(!nfc_device_parse_format_string(dev, temp_string)) { - break; - } - // Read and parse UID data from 2nd line - if(!file_worker_read_until(file_worker, temp_string, '\n')) { - break; - } - if(!nfc_device_parse_uid_string(dev, temp_string)) { + // Read and verify file header + uint32_t version = 0; + if(!flipper_file_read_header(file, temp_str, &version)) break; + if(string_cmp_str(temp_str, nfc_file_header) || (version != nfc_file_version)) { + depricated_version = true; break; } + // Read Nfc device type + if(!flipper_file_read_string(file, "Device type", temp_str)) break; + if(!nfc_device_parse_format_string(dev, temp_str)) break; + // Read and parse UID, ATQA and SAK + if(!flipper_file_get_value_count(file, "UID", &data_cnt)) break; + data->uid_len = data_cnt; + if(!flipper_file_read_hex(file, "UID", data->uid, data->uid_len)) break; + if(!flipper_file_read_hex(file, "ATQA", data->atqa, 2)) break; + if(!flipper_file_read_hex(file, "SAK", &data->sak, 1)) break; // Parse other data if(dev->format == NfcDeviceSaveFormatMifareUl) { - // Read until EOF - if(!file_worker_read_until(file_worker, temp_string, 0x05)) { - break; - } - if(!nfc_device_parse_mifare_ul_string(dev, temp_string)) { - break; - } + if(!nfc_device_load_mifare_ul_data(file, dev)) break; } else if(dev->format == NfcDeviceSaveFormatBankCard) { - // Read until EOF - if(!file_worker_read_until(file_worker, temp_string, 0x05)) { - break; - } - if(!nfc_device_parse_bank_card_string(dev, temp_string)) { - break; - } + if(!nfc_device_load_bank_card_data(file, dev)) break; } parsed = true; - } while(0); + } while(false); if(!parsed) { - file_worker_show_error(file_worker, "Can not parse\nfile"); + if(depricated_version) { + dialog_message_show_storage_error(dev->dialogs, "File format depricated"); + } else { + dialog_message_show_storage_error(dev->dialogs, "Can not parse\nfile"); + } } - string_clear(temp_string); + string_clear(temp_str); + flipper_file_close(file); + flipper_file_free(file); return parsed; } @@ -434,19 +347,16 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path) { furi_assert(dev); furi_assert(file_path); - FileWorker* file_worker = file_worker_alloc(false); // Load device data string_t path; string_init_set_str(path, file_path); - bool dev_load = nfc_device_load_data(file_worker, path, dev); + bool dev_load = nfc_device_load_data(dev, path); if(dev_load) { // Set device name path_extract_filename_no_ext(file_path, path); nfc_device_set_name(dev, string_get_cstr(path)); } string_clear(path); - file_worker_close(file_worker); - file_worker_free(file_worker); return dev_load; } @@ -454,10 +364,9 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path) { bool nfc_file_select(NfcDevice* dev) { furi_assert(dev); - FileWorker* file_worker = file_worker_alloc(false); // Input events and views are managed by file_select - bool res = file_worker_file_select( - file_worker, + bool res = dialog_file_select_show( + dev->dialogs, nfc_app_folder, nfc_app_extension, dev->file_name, @@ -465,18 +374,14 @@ bool nfc_file_select(NfcDevice* dev) { dev->dev_name); if(res) { string_t dev_str; - // Get key file path string_init_printf(dev_str, "%s/%s%s", nfc_app_folder, dev->file_name, nfc_app_extension); - - res = nfc_device_load_data(file_worker, dev_str, dev); + res = nfc_device_load_data(dev, dev_str); if(res) { nfc_device_set_name(dev, dev->file_name); } string_clear(dev_str); } - file_worker_close(file_worker); - file_worker_free(file_worker); return res; } @@ -491,61 +396,48 @@ void nfc_device_clear(NfcDevice* dev) { bool nfc_device_delete(NfcDevice* dev) { furi_assert(dev); - bool result = true; - FileWorker* file_worker = file_worker_alloc(false); + bool deleted = false; string_t file_path; + string_init(file_path); do { // Delete original file string_init_printf(file_path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension); - if(!file_worker_remove(file_worker, string_get_cstr(file_path))) { - result = false; - break; - } + if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break; // Delete shadow file if it exists if(dev->shadow_file_exist) { - string_clean(file_path); string_printf( file_path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_shadow_extension); - if(!file_worker_remove(file_worker, string_get_cstr(file_path))) { - result = false; - break; - } + if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break; } + deleted = true; } while(0); + if(!deleted) { + dialog_message_show_storage_error(dev->dialogs, "Can not remove file"); + } + string_clear(file_path); - file_worker_close(file_worker); - file_worker_free(file_worker); - return result; + return deleted; } bool nfc_device_restore(NfcDevice* dev) { furi_assert(dev); furi_assert(dev->shadow_file_exist); - bool result = true; - FileWorker* file_worker = file_worker_alloc(false); + bool restored = false; string_t path; do { string_init_printf( path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_shadow_extension); - if(!file_worker_remove(file_worker, string_get_cstr(path))) { - result = false; - break; - } + if(!storage_simply_remove(dev->storage, string_get_cstr(path))) break; dev->shadow_file_exist = false; - string_clean(path); string_printf(path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension); - if(!nfc_device_load_data(file_worker, path, dev)) { - result = false; - break; - } + if(!nfc_device_load_data(dev, path)) break; + restored = true; } while(0); string_clear(path); - file_worker_close(file_worker); - file_worker_free(file_worker); - return result; + return restored; } diff --git a/applications/nfc/nfc_device.h b/applications/nfc/nfc_device.h index 50f435ca..888f0c2f 100644 --- a/applications/nfc/nfc_device.h +++ b/applications/nfc/nfc_device.h @@ -2,6 +2,8 @@ #include #include +#include +#include #include "mifare_ultralight.h" @@ -57,6 +59,8 @@ typedef struct { } NfcDeviceData; typedef struct { + Storage* storage; + DialogsApp* dialogs; NfcDeviceData dev_data; char dev_name[NFC_DEV_NAME_MAX_LEN + 1]; char file_name[NFC_FILE_NAME_MAX_LEN]; @@ -64,6 +68,10 @@ typedef struct { bool shadow_file_exist; } NfcDevice; +NfcDevice* nfc_device_alloc(); + +void nfc_device_free(NfcDevice* nfc_dev); + void nfc_device_set_name(NfcDevice* dev, const char* name); bool nfc_device_save(NfcDevice* dev, const char* dev_name); diff --git a/applications/nfc/nfc_device_i.h b/applications/nfc/nfc_device_i.h deleted file mode 100644 index 01309eb5..00000000 --- a/applications/nfc/nfc_device_i.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "nfc_device.h" -#include - -uint16_t nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string); -bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string); - -uint16_t nfc_device_prepare_uid_string(NfcDevice* dev, string_t uid_string); -bool nfc_device_parse_uid_string(NfcDevice* dev, string_t uid_string); - -uint16_t nfc_device_prepare_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string); -bool nfc_device_parse_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string); - -uint16_t nfc_device_prepare_bank_card_string(NfcDevice* dev, string_t bank_card_string); -bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string); \ No newline at end of file diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h index 379cc100..61a11ce8 100755 --- a/applications/nfc/nfc_i.h +++ b/applications/nfc/nfc_i.h @@ -36,7 +36,7 @@ struct Nfc { Gui* gui; NotificationApp* notifications; SceneManager* scene_manager; - NfcDevice dev; + NfcDevice* dev; NfcDeviceCommonData dev_edit_data; char text_store[NFC_TEXT_STORE_SIZE + 1]; diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c old mode 100755 new mode 100644 index e8312b88..3f7f87e4 --- a/applications/nfc/nfc_worker.c +++ b/applications/nfc/nfc_worker.c @@ -3,14 +3,14 @@ #include "nfc_protocols/emv_decoder.h" #include "nfc_protocols/mifare_ultralight.h" -#define NFC_WORKER_TAG "nfc worker" +#define TAG "NfcWorker" /***************************** NFC Worker API *******************************/ NfcWorker* nfc_worker_alloc() { NfcWorker* nfc_worker = furi_alloc(sizeof(NfcWorker)); // Worker thread attributes - nfc_worker->thread_attr.name = "nfc_worker"; + nfc_worker->thread_attr.name = "NfcWorker"; nfc_worker->thread_attr.stack_size = 8192; nfc_worker->callback = NULL; nfc_worker->context = NULL; @@ -144,7 +144,7 @@ void nfc_worker_emulate(NfcWorker* nfc_worker) { NfcDeviceCommonData* data = &nfc_worker->dev_data->nfc_data; while(nfc_worker->state == NfcWorkerStateEmulate) { if(furi_hal_nfc_listen(data->uid, data->uid_len, data->atqa, data->sak, false, 100)) { - FURI_LOG_I(NFC_WORKER_TAG, "Reader detected"); + FURI_LOG_I(TAG, "Reader detected"); } osDelay(10); } @@ -174,18 +174,17 @@ void nfc_worker_read_emv_app(NfcWorker* nfc_worker) { result->nfc_data.uid, dev_list[0].dev.nfca.nfcId1, result->nfc_data.uid_len); result->nfc_data.protocol = NfcDeviceProtocolEMV; - FURI_LOG_I(NFC_WORKER_TAG, "Send select PPSE command"); + FURI_LOG_I(TAG, "Send select PPSE command"); tx_len = emv_prepare_select_ppse(tx_buff); err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); if(err != ERR_NONE) { - FURI_LOG_E(NFC_WORKER_TAG, "Error during selection PPSE request: %d", err); + FURI_LOG_E(TAG, "Error during selection PPSE request: %d", err); furi_hal_nfc_deactivate(); continue; } - FURI_LOG_I( - NFC_WORKER_TAG, "Select PPSE response received. Start parsing response"); + FURI_LOG_I(TAG, "Select PPSE response received. Start parsing response"); if(emv_decode_ppse_response(rx_buff, *rx_len, &emv_app)) { - FURI_LOG_I(NFC_WORKER_TAG, "Select PPSE responce parced"); + FURI_LOG_I(TAG, "Select PPSE responce parced"); // Notify caller and exit result->emv_data.aid_len = emv_app.aid_len; memcpy(result->emv_data.aid, emv_app.aid, emv_app.aid_len); @@ -194,18 +193,18 @@ void nfc_worker_read_emv_app(NfcWorker* nfc_worker) { } break; } else { - FURI_LOG_E(NFC_WORKER_TAG, "Can't find pay application"); + FURI_LOG_E(TAG, "Can't find pay application"); furi_hal_nfc_deactivate(); continue; } } else { // Can't find EMV card - FURI_LOG_W(NFC_WORKER_TAG, "Card doesn't support EMV"); + FURI_LOG_W(TAG, "Card doesn't support EMV"); furi_hal_nfc_deactivate(); } } else { // Can't find EMV card - FURI_LOG_W(NFC_WORKER_TAG, "Can't find any cards"); + FURI_LOG_W(TAG, "Can't find any cards"); furi_hal_nfc_deactivate(); } osDelay(20); @@ -236,56 +235,53 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) { result->nfc_data.uid, dev_list[0].dev.nfca.nfcId1, result->nfc_data.uid_len); result->nfc_data.protocol = NfcDeviceProtocolEMV; - FURI_LOG_I(NFC_WORKER_TAG, "Send select PPSE command"); + FURI_LOG_I(TAG, "Send select PPSE command"); tx_len = emv_prepare_select_ppse(tx_buff); err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); if(err != ERR_NONE) { - FURI_LOG_E(NFC_WORKER_TAG, "Error during selection PPSE request: %d", err); + FURI_LOG_E(TAG, "Error during selection PPSE request: %d", err); furi_hal_nfc_deactivate(); continue; } - FURI_LOG_I( - NFC_WORKER_TAG, "Select PPSE response received. Start parsing response"); + FURI_LOG_I(TAG, "Select PPSE response received. Start parsing response"); if(emv_decode_ppse_response(rx_buff, *rx_len, &emv_app)) { - FURI_LOG_I(NFC_WORKER_TAG, "Select PPSE responce parced"); + FURI_LOG_I(TAG, "Select PPSE responce parced"); + result->emv_data.aid_len = emv_app.aid_len; + memcpy(result->emv_data.aid, emv_app.aid, emv_app.aid_len); } else { - FURI_LOG_E(NFC_WORKER_TAG, "Can't find pay application"); + FURI_LOG_E(TAG, "Can't find pay application"); furi_hal_nfc_deactivate(); continue; } - FURI_LOG_I(NFC_WORKER_TAG, "Starting application ..."); + FURI_LOG_I(TAG, "Starting application ..."); tx_len = emv_prepare_select_app(tx_buff, &emv_app); err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); if(err != ERR_NONE) { - FURI_LOG_E( - NFC_WORKER_TAG, "Error during application selection request: %d", err); + FURI_LOG_E(TAG, "Error during application selection request: %d", err); furi_hal_nfc_deactivate(); continue; } - FURI_LOG_I( - NFC_WORKER_TAG, - "Select application response received. Start parsing response"); + FURI_LOG_I(TAG, "Select application response received. Start parsing response"); if(emv_decode_select_app_response(rx_buff, *rx_len, &emv_app)) { - FURI_LOG_I(NFC_WORKER_TAG, "Card name: %s", emv_app.name); + FURI_LOG_I(TAG, "Card name: %s", emv_app.name); memcpy(result->emv_data.name, emv_app.name, sizeof(emv_app.name)); } else if(emv_app.pdol.size > 0) { - FURI_LOG_W(NFC_WORKER_TAG, "Can't find card name, but PDOL is present."); + FURI_LOG_W(TAG, "Can't find card name, but PDOL is present."); } else { - FURI_LOG_E(NFC_WORKER_TAG, "Can't find card name or PDOL"); + FURI_LOG_E(TAG, "Can't find card name or PDOL"); furi_hal_nfc_deactivate(); continue; } - FURI_LOG_I(NFC_WORKER_TAG, "Starting Get Processing Options command ..."); + FURI_LOG_I(TAG, "Starting Get Processing Options command ..."); tx_len = emv_prepare_get_proc_opt(tx_buff, &emv_app); err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); if(err != ERR_NONE) { - FURI_LOG_E( - NFC_WORKER_TAG, "Error during Get Processing Options command: %d", err); + FURI_LOG_E(TAG, "Error during Get Processing Options command: %d", err); furi_hal_nfc_deactivate(); continue; } if(emv_decode_get_proc_opt(rx_buff, *rx_len, &emv_app)) { - FURI_LOG_I(NFC_WORKER_TAG, "Card number parsed"); + FURI_LOG_I(TAG, "Card number parsed"); result->emv_data.number_len = emv_app.card_number_len; memcpy(result->emv_data.number, emv_app.card_number, emv_app.card_number_len); // Notify caller and exit @@ -309,7 +305,7 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) { tx_buff, tx_len, &rx_buff, &rx_len, false); if(err != ERR_NONE) { FURI_LOG_E( - NFC_WORKER_TAG, + TAG, "Error reading application sfi %d, record %d", sfi, record); @@ -321,7 +317,7 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) { } } if(pan_found) { - FURI_LOG_I(NFC_WORKER_TAG, "Card PAN found"); + FURI_LOG_I(TAG, "Card PAN found"); result->emv_data.number_len = emv_app.card_number_len; memcpy( result->emv_data.number, @@ -343,18 +339,18 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) { } break; } else { - FURI_LOG_E(NFC_WORKER_TAG, "Can't read card number"); + FURI_LOG_E(TAG, "Can't read card number"); } furi_hal_nfc_deactivate(); } } else { // Can't find EMV card - FURI_LOG_W(NFC_WORKER_TAG, "Card doesn't support EMV"); + FURI_LOG_W(TAG, "Card doesn't support EMV"); furi_hal_nfc_deactivate(); } } else { // Can't find EMV card - FURI_LOG_W(NFC_WORKER_TAG, "Can't find any cards"); + FURI_LOG_W(TAG, "Can't find any cards"); furi_hal_nfc_deactivate(); } osDelay(20); @@ -416,63 +412,63 @@ void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { while(nfc_worker->state == NfcWorkerStateEmulateApdu) { if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 300)) { - FURI_LOG_I(NFC_WORKER_TAG, "POS terminal detected"); + FURI_LOG_I(TAG, "POS terminal detected"); // Read data from POS terminal err = furi_hal_nfc_data_exchange(NULL, 0, &rx_buff, &rx_len, false); if(err == ERR_NONE) { - FURI_LOG_I(NFC_WORKER_TAG, "Received Select PPSE"); + FURI_LOG_I(TAG, "Received Select PPSE"); } else { - FURI_LOG_E(NFC_WORKER_TAG, "Error in 1st data exchange: select PPSE"); + FURI_LOG_E(TAG, "Error in 1st data exchange: select PPSE"); furi_hal_nfc_deactivate(); continue; } - FURI_LOG_I(NFC_WORKER_TAG, "Transive SELECT PPSE ANS"); + FURI_LOG_I(TAG, "Transive SELECT PPSE ANS"); tx_len = emv_select_ppse_ans(tx_buff); err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); if(err == ERR_NONE) { - FURI_LOG_I(NFC_WORKER_TAG, "Received Select APP"); + FURI_LOG_I(TAG, "Received Select APP"); } else { - FURI_LOG_E(NFC_WORKER_TAG, "Error in 2nd data exchange: select APP"); + FURI_LOG_E(TAG, "Error in 2nd data exchange: select APP"); furi_hal_nfc_deactivate(); continue; } - FURI_LOG_I(NFC_WORKER_TAG, "Transive SELECT APP ANS"); + FURI_LOG_I(TAG, "Transive SELECT APP ANS"); tx_len = emv_select_app_ans(tx_buff); err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); if(err == ERR_NONE) { - FURI_LOG_I(NFC_WORKER_TAG, "Received PDOL"); + FURI_LOG_I(TAG, "Received PDOL"); } else { - FURI_LOG_E(NFC_WORKER_TAG, "Error in 3rd data exchange: receive PDOL"); + FURI_LOG_E(TAG, "Error in 3rd data exchange: receive PDOL"); furi_hal_nfc_deactivate(); continue; } - FURI_LOG_I(NFC_WORKER_TAG, "Transive PDOL ANS"); + FURI_LOG_I(TAG, "Transive PDOL ANS"); tx_len = emv_get_proc_opt_ans(tx_buff); err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); if(err == ERR_NONE) { - FURI_LOG_I(NFC_WORKER_TAG, "Transive PDOL ANS"); + FURI_LOG_I(TAG, "Transive PDOL ANS"); } else { - FURI_LOG_E(NFC_WORKER_TAG, "Error in 4rd data exchange: Transive PDOL ANS"); + FURI_LOG_E(TAG, "Error in 4rd data exchange: Transive PDOL ANS"); furi_hal_nfc_deactivate(); continue; } if(*rx_len != sizeof(debug_rx) || memcmp(rx_buff, debug_rx, sizeof(debug_rx))) { - FURI_LOG_E(NFC_WORKER_TAG, "Failed long message test"); + FURI_LOG_E(TAG, "Failed long message test"); } else { - FURI_LOG_I(NFC_WORKER_TAG, "Correct debug message received"); + FURI_LOG_I(TAG, "Correct debug message received"); tx_len = sizeof(debug_tx); err = furi_hal_nfc_data_exchange( (uint8_t*)debug_tx, tx_len, &rx_buff, &rx_len, false); if(err == ERR_NONE) { - FURI_LOG_I(NFC_WORKER_TAG, "Transive Debug message"); + FURI_LOG_I(TAG, "Transive Debug message"); } } furi_hal_nfc_deactivate(); } else { - FURI_LOG_W(NFC_WORKER_TAG, "Can't find reader"); + FURI_LOG_W(TAG, "Can't find reader"); } osDelay(20); } @@ -499,71 +495,69 @@ void nfc_worker_read_mifare_ul(NfcWorker* nfc_worker) { dev_list[0].dev.nfca.sensRes.platformInfo, dev_list[0].dev.nfca.selRes.sak)) { // Get Mifare Ultralight version - FURI_LOG_I(NFC_WORKER_TAG, "Found Mifare Ultralight tag. Reading tag version"); + FURI_LOG_I(TAG, "Found Mifare Ultralight tag. Reading tag version"); tx_len = mf_ul_prepare_get_version(tx_buff); err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); if(err == ERR_NONE) { mf_ul_parse_get_version_response(rx_buff, &mf_ul_read); FURI_LOG_I( - NFC_WORKER_TAG, + TAG, "Mifare Ultralight Type: %d, Pages: %d", mf_ul_read.type, mf_ul_read.pages_to_read); - FURI_LOG_I(NFC_WORKER_TAG, "Reading signature ..."); + FURI_LOG_I(TAG, "Reading signature ..."); tx_len = mf_ul_prepare_read_signature(tx_buff); if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) { - FURI_LOG_W(NFC_WORKER_TAG, "Failed reading signature"); + FURI_LOG_W(TAG, "Failed reading signature"); memset(mf_ul_read.data.signature, 0, sizeof(mf_ul_read.data.signature)); } else { mf_ul_parse_read_signature_response(rx_buff, &mf_ul_read); } } else if(err == ERR_TIMEOUT) { FURI_LOG_W( - NFC_WORKER_TAG, + TAG, "Card doesn't respond to GET VERSION command. Setting default read parameters"); err = ERR_NONE; mf_ul_set_default_version(&mf_ul_read); // Reinit device furi_hal_nfc_deactivate(); if(!furi_hal_nfc_detect(&dev_list, &dev_cnt, 300, false)) { - FURI_LOG_E(NFC_WORKER_TAG, "Lost connection. Restarting search"); + FURI_LOG_E(TAG, "Lost connection. Restarting search"); continue; } } else { FURI_LOG_E( - NFC_WORKER_TAG, - "Error getting Mifare Ultralight version. Error code: %d", - err); + TAG, "Error getting Mifare Ultralight version. Error code: %d", err); continue; } if(mf_ul_read.support_fast_read) { - FURI_LOG_I(NFC_WORKER_TAG, "Reading pages ..."); + FURI_LOG_I(TAG, "Reading pages ..."); tx_len = mf_ul_prepare_fast_read(tx_buff, 0x00, mf_ul_read.pages_to_read - 1); if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) { - FURI_LOG_E(NFC_WORKER_TAG, "Failed reading pages"); + FURI_LOG_E(TAG, "Failed reading pages"); continue; } else { mf_ul_parse_fast_read_response( rx_buff, 0x00, mf_ul_read.pages_to_read - 1, &mf_ul_read); } - FURI_LOG_I(NFC_WORKER_TAG, "Reading 3 counters ..."); + FURI_LOG_I(TAG, "Reading 3 counters ..."); for(uint8_t i = 0; i < 3; i++) { tx_len = mf_ul_prepare_read_cnt(tx_buff, i); if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) { - FURI_LOG_W(NFC_WORKER_TAG, "Failed reading Counter %d", i); + FURI_LOG_W(TAG, "Failed reading Counter %d", i); mf_ul_read.data.counter[i] = 0; } else { mf_ul_parse_read_cnt_response(rx_buff, i, &mf_ul_read); } } - FURI_LOG_I(NFC_WORKER_TAG, "Checking tearing flags ..."); + FURI_LOG_I(TAG, "Checking tearing flags ..."); for(uint8_t i = 0; i < 3; i++) { tx_len = mf_ul_prepare_check_tearing(tx_buff, i); if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) { - FURI_LOG_E(NFC_WORKER_TAG, "Error checking tearing flag %d", i); + FURI_LOG_E(TAG, "Error checking tearing flag %d", i); mf_ul_read.data.tearing[i] = MF_UL_TEARING_FLAG_DEFAULT; } else { mf_ul_parse_check_tearing_response(rx_buff, i, &mf_ul_read); @@ -572,11 +566,10 @@ void nfc_worker_read_mifare_ul(NfcWorker* nfc_worker) { } else { // READ card with READ command (4 pages at a time) for(uint8_t page = 0; page < mf_ul_read.pages_to_read; page += 4) { - FURI_LOG_I(NFC_WORKER_TAG, "Reading pages %d - %d ...", page, page + 3); + FURI_LOG_I(TAG, "Reading pages %d - %d ...", page, page + 3); tx_len = mf_ul_prepare_read(tx_buff, page); if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) { - FURI_LOG_E( - NFC_WORKER_TAG, "Read pages %d - %d failed", page, page + 3); + FURI_LOG_E(TAG, "Read pages %d - %d failed", page, page + 3); continue; } else { mf_ul_parse_read_response(rx_buff, page, &mf_ul_read); @@ -600,10 +593,10 @@ void nfc_worker_read_mifare_ul(NfcWorker* nfc_worker) { } break; } else { - FURI_LOG_W(NFC_WORKER_TAG, "Tag does not support Mifare Ultralight"); + FURI_LOG_W(TAG, "Tag does not support Mifare Ultralight"); } } else { - FURI_LOG_W(NFC_WORKER_TAG, "Can't find any tags"); + FURI_LOG_W(TAG, "Can't find any tags"); } osDelay(100); } @@ -627,7 +620,7 @@ void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) { data->nfc_data.sak, true, 200)) { - FURI_LOG_D(NFC_WORKER_TAG, "Anticollision passed"); + FURI_LOG_D(TAG, "Anticollision passed"); if(furi_hal_nfc_get_first_frame(&rx_buff, &rx_len)) { // Data exchange loop while(nfc_worker->state == NfcWorkerStateEmulateMifareUl) { @@ -639,17 +632,17 @@ void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) { if(err == ERR_NONE) { continue; } else { - FURI_LOG_E(NFC_WORKER_TAG, "Communication error: %d", err); + FURI_LOG_E(TAG, "Communication error: %d", err); break; } } else { - FURI_LOG_W(NFC_WORKER_TAG, "Not valid command: %02X", rx_buff[0]); + FURI_LOG_W(TAG, "Not valid command: %02X", rx_buff[0]); furi_hal_nfc_deactivate(); break; } } } else { - FURI_LOG_W(NFC_WORKER_TAG, "Error in 1st data exchange"); + FURI_LOG_W(TAG, "Error in 1st data exchange"); furi_hal_nfc_deactivate(); } } @@ -660,7 +653,7 @@ void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) { nfc_worker->callback(nfc_worker->context); } } - FURI_LOG_W(NFC_WORKER_TAG, "Can't find reader"); + FURI_LOG_W(TAG, "Can't find reader"); osThreadYield(); } } diff --git a/applications/nfc/scenes/nfc_scene_card_menu.c b/applications/nfc/scenes/nfc_scene_card_menu.c index dbaefe4f..5724abdb 100755 --- a/applications/nfc/scenes/nfc_scene_card_menu.c +++ b/applications/nfc/scenes/nfc_scene_card_menu.c @@ -17,7 +17,7 @@ void nfc_scene_card_menu_on_enter(void* context) { Nfc* nfc = (Nfc*)context; Submenu* submenu = nfc->submenu; - if(nfc->dev.dev_data.nfc_data.protocol > NfcDeviceProtocolUnknown) { + if(nfc->dev->dev_data.nfc_data.protocol > NfcDeviceProtocolUnknown) { submenu_add_item( submenu, "Run compatible app", @@ -48,9 +48,9 @@ bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) { if(event.event == SubmenuIndexRunApp) { scene_manager_set_scene_state( nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexRunApp); - if(nfc->dev.dev_data.nfc_data.protocol == NfcDeviceProtocolMifareUl) { + if(nfc->dev->dev_data.nfc_data.protocol == NfcDeviceProtocolMifareUl) { scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUl); - } else if(nfc->dev.dev_data.nfc_data.protocol == NfcDeviceProtocolEMV) { + } else if(nfc->dev->dev_data.nfc_data.protocol == NfcDeviceProtocolEMV) { scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvApp); } return true; @@ -66,7 +66,7 @@ bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) { return true; } else if(event.event == SubmenuIndexSave) { scene_manager_set_scene_state(nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexSave); - nfc->dev.format = NfcDeviceSaveFormatUid; + nfc->dev->format = NfcDeviceSaveFormatUid; scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); return true; } diff --git a/applications/nfc/scenes/nfc_scene_delete.c b/applications/nfc/scenes/nfc_scene_delete.c index 0ea1b214..498e6ecd 100755 --- a/applications/nfc/scenes/nfc_scene_delete.c +++ b/applications/nfc/scenes/nfc_scene_delete.c @@ -12,14 +12,14 @@ void nfc_scene_delete_on_enter(void* context) { // Setup Custom Widget view char delete_str[64]; - snprintf(delete_str, sizeof(delete_str), "\e#Delete %s\e#", nfc->dev.dev_name); + snprintf(delete_str, sizeof(delete_str), "\e#Delete %s\e#", nfc->dev->dev_name); widget_add_text_box_element(nfc->widget, 0, 0, 128, 24, AlignCenter, AlignCenter, delete_str); widget_add_button_element( nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_delete_widget_callback, nfc); widget_add_button_element( nfc->widget, GuiButtonTypeRight, "Delete", nfc_scene_delete_widget_callback, nfc); char uid_str[32]; - NfcDeviceCommonData* data = &nfc->dev.dev_data.nfc_data; + NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data; if(data->uid_len == 4) { snprintf( uid_str, @@ -73,7 +73,7 @@ bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) { if(event.event == GuiButtonTypeLeft) { return scene_manager_previous_scene(nfc->scene_manager); } else if(event.event == GuiButtonTypeRight) { - if(nfc_device_delete(&nfc->dev)) { + if(nfc_device_delete(nfc->dev)) { scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess); } else { scene_manager_search_and_switch_to_previous_scene( diff --git a/applications/nfc/scenes/nfc_scene_device_info.c b/applications/nfc/scenes/nfc_scene_device_info.c index 54196a32..d57327b7 100755 --- a/applications/nfc/scenes/nfc_scene_device_info.c +++ b/applications/nfc/scenes/nfc_scene_device_info.c @@ -1,4 +1,5 @@ #include "../nfc_i.h" +#include "../helpers/nfc_emv_parser.h" #define NFC_SCENE_DEVICE_INFO_BACK_EVENT (0UL) @@ -36,13 +37,13 @@ void nfc_scene_device_info_on_enter(void* context) { // Setup Custom Widget view widget_add_text_box_element( - nfc->widget, 0, 0, 128, 24, AlignCenter, AlignCenter, nfc->dev.dev_name); + nfc->widget, 0, 0, 128, 24, AlignCenter, AlignCenter, nfc->dev->dev_name); widget_add_button_element( nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_device_info_widget_callback, nfc); widget_add_button_element( nfc->widget, GuiButtonTypeRight, "Data", nfc_scene_device_info_widget_callback, nfc); char uid_str[32]; - NfcDeviceCommonData* data = &nfc->dev.dev_data.nfc_data; + NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data; if(data->uid_len == 4) { snprintf( uid_str, @@ -87,14 +88,14 @@ void nfc_scene_device_info_on_enter(void* context) { widget_add_string_element(nfc->widget, 118, 42, AlignRight, AlignTop, FontSecondary, atqa_str); // Setup Data View - if(nfc->dev.format == NfcDeviceSaveFormatUid) { + if(nfc->dev->format == NfcDeviceSaveFormatUid) { DialogEx* dialog_ex = nfc->dialog_ex; dialog_ex_set_left_button_text(dialog_ex, "Back"); dialog_ex_set_text(dialog_ex, "No data", 64, 32, AlignCenter, AlignCenter); dialog_ex_set_context(dialog_ex, nfc); dialog_ex_set_result_callback(dialog_ex, nfc_scene_device_info_dialog_callback); - } else if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) { - MifareUlData* mf_ul_data = (MifareUlData*)&nfc->dev.dev_data.mf_ul_data; + } else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { + MifareUlData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data; TextBox* text_box = nfc->text_box; text_box_set_context(text_box, nfc); text_box_set_exit_callback(text_box, nfc_scene_device_info_text_box_callback); @@ -107,8 +108,8 @@ void nfc_scene_device_info_on_enter(void* context) { nfc->text_box_store, "%02X%02X ", mf_ul_data->data[i], mf_ul_data->data[i + 1]); } text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); - } else if(nfc->dev.format == NfcDeviceSaveFormatBankCard) { - NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data; + } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { + NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data; BankCard* bank_card = nfc->bank_card; bank_card_set_name(bank_card, emv_data->name); bank_card_set_number(bank_card, emv_data->number, emv_data->number_len); @@ -116,12 +117,29 @@ void nfc_scene_device_info_on_enter(void* context) { if(emv_data->exp_mon) { bank_card_set_exp_date(bank_card, emv_data->exp_mon, emv_data->exp_year); } + string_t display_str; + string_init(display_str); if(emv_data->country_code) { - bank_card_set_country_name(bank_card, emv_data->country_code); + string_t country_name; + string_init(country_name); + if(nfc_emv_parser_get_country_name( + nfc->dev->storage, emv_data->country_code, country_name)) { + string_printf(display_str, "Reg:%s", string_get_cstr(country_name)); + bank_card_set_country_name(bank_card, string_get_cstr(display_str)); + } + string_clear(country_name); } if(emv_data->currency_code) { - bank_card_set_currency_name(bank_card, emv_data->currency_code); + string_t currency_name; + string_init(currency_name); + if(nfc_emv_parser_get_currency_name( + nfc->dev->storage, emv_data->country_code, currency_name)) { + string_printf(display_str, "Cur:%s", string_get_cstr(currency_name)); + bank_card_set_currency_name(bank_card, string_get_cstr(display_str)); + } + string_clear(currency_name); } + string_clear(display_str); } scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); @@ -136,17 +154,17 @@ bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) { if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeLeft)) { consumed = scene_manager_previous_scene(nfc->scene_manager); } else if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeRight)) { - if(nfc->dev.format == NfcDeviceSaveFormatUid) { + if(nfc->dev->format == NfcDeviceSaveFormatUid) { scene_manager_set_scene_state( nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); consumed = true; - } else if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) { + } else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { scene_manager_set_scene_state( nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); consumed = true; - } else if(nfc->dev.format == NfcDeviceSaveFormatBankCard) { + } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { scene_manager_set_scene_state( nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewBankCard); @@ -168,7 +186,7 @@ void nfc_scene_device_info_on_exit(void* context) { // Clear Custom Widget widget_clear(nfc->widget); - if(nfc->dev.format == NfcDeviceSaveFormatUid) { + if(nfc->dev->format == NfcDeviceSaveFormatUid) { // Clear Dialog DialogEx* dialog_ex = nfc->dialog_ex; dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter); @@ -179,11 +197,11 @@ void nfc_scene_device_info_on_exit(void* context) { dialog_ex_set_center_button_text(dialog_ex, NULL); dialog_ex_set_result_callback(dialog_ex, NULL); dialog_ex_set_context(dialog_ex, NULL); - } else if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) { + } else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { // Clear TextBox text_box_clean(nfc->text_box); string_clean(nfc->text_box_store); - } else if(nfc->dev.format == NfcDeviceSaveFormatBankCard) { + } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { // Clear Bank Card bank_card_clear(nfc->bank_card); } diff --git a/applications/nfc/scenes/nfc_scene_emulate_apdu_sequence.c b/applications/nfc/scenes/nfc_scene_emulate_apdu_sequence.c index b08660b3..c9e822e2 100644 --- a/applications/nfc/scenes/nfc_scene_emulate_apdu_sequence.c +++ b/applications/nfc/scenes/nfc_scene_emulate_apdu_sequence.c @@ -11,7 +11,7 @@ void nfc_scene_emulate_apdu_sequence_on_enter(void* context) { // Setup and start worker view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - nfc_worker_start(nfc->worker, NfcWorkerStateEmulateApdu, &nfc->dev.dev_data, NULL, nfc); + nfc_worker_start(nfc->worker, NfcWorkerStateEmulateApdu, &nfc->dev->dev_data, NULL, nfc); } bool nfc_scene_emulate_apdu_sequence_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c b/applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c index cba09437..bacdd347 100755 --- a/applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c +++ b/applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c @@ -14,8 +14,8 @@ void nfc_scene_emulate_mifare_ul_on_enter(void* context) { // Setup view Popup* popup = nfc->popup; - if(strcmp(nfc->dev.dev_name, "")) { - nfc_text_store_set(nfc, "%s", nfc->dev.dev_name); + if(strcmp(nfc->dev->dev_name, "")) { + nfc_text_store_set(nfc, "%s", nfc->dev->dev_name); } popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61); popup_set_header(popup, "Emulating\nMf Ultralight", 56, 31, AlignLeft, AlignTop); @@ -25,7 +25,7 @@ void nfc_scene_emulate_mifare_ul_on_enter(void* context) { nfc_worker_start( nfc->worker, NfcWorkerStateEmulateMifareUl, - &nfc->dev.dev_data, + &nfc->dev->dev_data, nfc_emulate_mifare_ul_worker_callback, nfc); } @@ -45,7 +45,7 @@ bool nfc_scene_emulate_mifare_ul_on_event(void* context, SceneManagerEvent event NFC_MF_UL_DATA_CHANGED) { scene_manager_set_scene_state( nfc->scene_manager, NfcSceneEmulateMifareUl, NFC_MF_UL_DATA_NOT_CHANGED); - nfc_device_save_shadow(&nfc->dev, nfc->dev.dev_name); + nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name); } consumed = false; } diff --git a/applications/nfc/scenes/nfc_scene_emulate_uid.c b/applications/nfc/scenes/nfc_scene_emulate_uid.c index ccd27de5..a8fff57b 100755 --- a/applications/nfc/scenes/nfc_scene_emulate_uid.c +++ b/applications/nfc/scenes/nfc_scene_emulate_uid.c @@ -5,10 +5,10 @@ void nfc_scene_emulate_uid_on_enter(void* context) { // Setup view Popup* popup = nfc->popup; - NfcDeviceCommonData* data = &nfc->dev.dev_data.nfc_data; + NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data; - if(strcmp(nfc->dev.dev_name, "")) { - nfc_text_store_set(nfc, "%s", nfc->dev.dev_name); + if(strcmp(nfc->dev->dev_name, "")) { + nfc_text_store_set(nfc, "%s", nfc->dev->dev_name); } else if(data->uid_len == 4) { nfc_text_store_set( nfc, "%02X %02X %02X %02X", data->uid[0], data->uid[1], data->uid[2], data->uid[3]); @@ -32,7 +32,7 @@ void nfc_scene_emulate_uid_on_enter(void* context) { // Setup and start worker view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - nfc_worker_start(nfc->worker, NfcWorkerStateEmulate, &nfc->dev.dev_data, NULL, nfc); + nfc_worker_start(nfc->worker, NfcWorkerStateEmulate, &nfc->dev->dev_data, NULL, nfc); } bool nfc_scene_emulate_uid_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/nfc/scenes/nfc_scene_file_select.c b/applications/nfc/scenes/nfc_scene_file_select.c index 67894fbf..010e807e 100755 --- a/applications/nfc/scenes/nfc_scene_file_select.c +++ b/applications/nfc/scenes/nfc_scene_file_select.c @@ -3,7 +3,7 @@ void nfc_scene_file_select_on_enter(void* context) { Nfc* nfc = (Nfc*)context; // Process file_select return - if(nfc_file_select(&nfc->dev)) { + if(nfc_file_select(nfc->dev)) { scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu); } else { scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart); diff --git a/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c b/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c index 236da374..344d4733 100755 --- a/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c +++ b/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c @@ -32,9 +32,9 @@ bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent event) { if(event.event == SubmenuIndexSave) { scene_manager_set_scene_state( nfc->scene_manager, NfcSceneMifareUlMenu, SubmenuIndexSave); - nfc->dev.format = NfcDeviceSaveFormatMifareUl; + nfc->dev->format = NfcDeviceSaveFormatMifareUl; // Clear device name - nfc_device_set_name(&nfc->dev, ""); + nfc_device_set_name(nfc->dev, ""); scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); return true; } else if(event.event == SubmenuIndexEmulate) { diff --git a/applications/nfc/scenes/nfc_scene_read_card.c b/applications/nfc/scenes/nfc_scene_read_card.c index 8853858e..d01fa75d 100755 --- a/applications/nfc/scenes/nfc_scene_read_card.c +++ b/applications/nfc/scenes/nfc_scene_read_card.c @@ -18,7 +18,7 @@ void nfc_scene_read_card_on_enter(void* context) { // Start worker view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); nfc_worker_start( - nfc->worker, NfcWorkerStateDetect, &nfc->dev.dev_data, nfc_read_card_worker_callback, nfc); + nfc->worker, NfcWorkerStateDetect, &nfc->dev->dev_data, nfc_read_card_worker_callback, nfc); } bool nfc_scene_read_card_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/nfc/scenes/nfc_scene_read_card_success.c b/applications/nfc/scenes/nfc_scene_read_card_success.c index 5cac8258..c70bf1b2 100755 --- a/applications/nfc/scenes/nfc_scene_read_card_success.c +++ b/applications/nfc/scenes/nfc_scene_read_card_success.c @@ -15,7 +15,7 @@ void nfc_scene_read_card_success_on_enter(void* context) { notification_message(nfc->notifications, &sequence_success); // Setup view - NfcDeviceCommonData* data = (NfcDeviceCommonData*)&nfc->dev.dev_data.nfc_data; + NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data; DialogEx* dialog_ex = nfc->dialog_ex; dialog_ex_set_left_button_text(dialog_ex, "Retry"); dialog_ex_set_right_button_text(dialog_ex, "More"); @@ -68,7 +68,7 @@ bool nfc_scene_read_card_success_on_event(void* context, SceneManagerEvent event return scene_manager_previous_scene(nfc->scene_manager); } else if(event.event == DialogExResultRight) { // Clear device name - nfc_device_set_name(&nfc->dev, ""); + nfc_device_set_name(nfc->dev, ""); scene_manager_next_scene(nfc->scene_manager, NfcSceneCardMenu); return true; } diff --git a/applications/nfc/scenes/nfc_scene_read_emv_app.c b/applications/nfc/scenes/nfc_scene_read_emv_app.c index 63509ad8..665a121b 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_app.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_app.c @@ -20,7 +20,7 @@ void nfc_scene_read_emv_app_on_enter(void* context) { nfc_worker_start( nfc->worker, NfcWorkerStateReadEMVApp, - &nfc->dev.dev_data, + &nfc->dev->dev_data, nfc_read_emv_app_worker_callback, nfc); } diff --git a/applications/nfc/scenes/nfc_scene_read_emv_app_success.c b/applications/nfc/scenes/nfc_scene_read_emv_app_success.c index bea8d719..3fe62f3f 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_app_success.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_app_success.c @@ -13,8 +13,8 @@ void nfc_scene_read_emv_app_success_on_enter(void* context) { Nfc* nfc = (Nfc*)context; // Setup view - NfcDeviceCommonData* nfc_data = &nfc->dev.dev_data.nfc_data; - NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data; + NfcDeviceCommonData* nfc_data = &nfc->dev->dev_data.nfc_data; + NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data; DialogEx* dialog_ex = nfc->dialog_ex; dialog_ex_set_left_button_text(dialog_ex, "Retry"); dialog_ex_set_right_button_text(dialog_ex, "Run app"); @@ -23,7 +23,8 @@ void nfc_scene_read_emv_app_success_on_enter(void* context) { // Display UID and AID string_t aid; string_init(aid); - bool aid_found = nfc_emv_parser_get_aid_name(emv_data->aid, emv_data->aid_len, aid); + bool aid_found = + nfc_emv_parser_get_aid_name(nfc->dev->storage, emv_data->aid, emv_data->aid_len, aid); if(!aid_found) { for(uint8_t i = 0; i < emv_data->aid_len; i++) { string_cat_printf(aid, "%02X", emv_data->aid[i]); diff --git a/applications/nfc/scenes/nfc_scene_read_emv_data.c b/applications/nfc/scenes/nfc_scene_read_emv_data.c index 953ac36f..4da1aaa7 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_data.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_data.c @@ -17,12 +17,12 @@ void nfc_scene_read_emv_data_on_enter(void* context) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); // Clear emv data - memset(&nfc->dev.dev_data.emv_data, 0, sizeof(nfc->dev.dev_data.emv_data)); + memset(&nfc->dev->dev_data.emv_data, 0, sizeof(nfc->dev->dev_data.emv_data)); // Start worker nfc_worker_start( nfc->worker, NfcWorkerStateReadEMV, - &nfc->dev.dev_data, + &nfc->dev->dev_data, nfc_read_emv_data_worker_callback, nfc); } diff --git a/applications/nfc/scenes/nfc_scene_read_emv_data_success.c b/applications/nfc/scenes/nfc_scene_read_emv_data_success.c index 92402c13..0867311f 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_data_success.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_data_success.c @@ -13,8 +13,8 @@ void nfc_scene_read_emv_data_success_widget_callback( void nfc_scene_read_emv_data_success_on_enter(void* context) { Nfc* nfc = (Nfc*)context; - NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data; - NfcDeviceCommonData* nfc_data = &nfc->dev.dev_data.nfc_data; + NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data; + NfcDeviceCommonData* nfc_data = &nfc->dev->dev_data.nfc_data; // Setup Custom Widget view // Add frame @@ -34,7 +34,7 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) { nfc); // Add card name widget_add_string_element( - nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev.dev_data.emv_data.name); + nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev->dev_data.emv_data.name); // Add cad number string_t pan_str; string_init(pan_str); @@ -49,7 +49,7 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) { string_t country_name; string_init(country_name); if((emv_data->country_code) && - nfc_emv_parser_get_country_name(emv_data->country_code, country_name)) { + nfc_emv_parser_get_country_name(nfc->dev->storage, emv_data->country_code, country_name)) { string_t disp_country; string_init_printf(disp_country, "Reg:%s", country_name); widget_add_string_element( @@ -61,7 +61,8 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) { string_t currency_name; string_init(currency_name); if((emv_data->currency_code) && - nfc_emv_parser_get_currency_name(emv_data->currency_code, currency_name)) { + nfc_emv_parser_get_currency_name( + nfc->dev->storage, emv_data->currency_code, currency_name)) { string_t disp_currency; string_init_printf(disp_currency, "Cur:%s", currency_name); widget_add_string_element( @@ -122,8 +123,8 @@ bool nfc_scene_read_emv_data_success_on_event(void* context, SceneManagerEvent e nfc->scene_manager, NfcSceneReadEmvAppSuccess); } else if(event.event == GuiButtonTypeRight) { // Clear device name - nfc_device_set_name(&nfc->dev, ""); - nfc->dev.format = NfcDeviceSaveFormatBankCard; + nfc_device_set_name(nfc->dev, ""); + nfc->dev->format = NfcDeviceSaveFormatBankCard; scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); return true; } diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_ul.c b/applications/nfc/scenes/nfc_scene_read_mifare_ul.c index f4d4a6dc..a0bd057d 100755 --- a/applications/nfc/scenes/nfc_scene_read_mifare_ul.c +++ b/applications/nfc/scenes/nfc_scene_read_mifare_ul.c @@ -20,7 +20,7 @@ void nfc_scene_read_mifare_ul_on_enter(void* context) { nfc_worker_start( nfc->worker, NfcWorkerStateReadMifareUl, - &nfc->dev.dev_data, + &nfc->dev->dev_data, nfc_read_mifare_ul_worker_callback, nfc); } 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 55571666..b12b14a7 100755 --- a/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c +++ b/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c @@ -27,7 +27,7 @@ void nfc_scene_read_mifare_ul_success_on_enter(void* context) { notification_message(nfc->notifications, &sequence_success); // Setup dialog view - NfcDeviceCommonData* data = (NfcDeviceCommonData*)&nfc->dev.dev_data.nfc_data; + NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data; DialogEx* dialog_ex = nfc->dialog_ex; dialog_ex_set_left_button_text(dialog_ex, "Retry"); dialog_ex_set_right_button_text(dialog_ex, "More"); @@ -54,7 +54,7 @@ void nfc_scene_read_mifare_ul_success_on_enter(void* context) { dialog_ex_set_result_callback(dialog_ex, nfc_scene_read_mifare_ul_success_dialog_callback); // Setup TextBox view - MifareUlData* mf_ul_data = (MifareUlData*)&nfc->dev.dev_data.mf_ul_data; + MifareUlData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data; TextBox* text_box = nfc->text_box; text_box_set_context(text_box, nfc); text_box_set_exit_callback(text_box, nfc_scene_read_mifare_ul_success_text_box_callback); diff --git a/applications/nfc/scenes/nfc_scene_save_name.c b/applications/nfc/scenes/nfc_scene_save_name.c index ca3afdac..44babcdd 100755 --- a/applications/nfc/scenes/nfc_scene_save_name.c +++ b/applications/nfc/scenes/nfc_scene_save_name.c @@ -15,11 +15,11 @@ void nfc_scene_save_name_on_enter(void* context) { // Setup view TextInput* text_input = nfc->text_input; bool dev_name_empty = false; - if(!strcmp(nfc->dev.dev_name, "")) { + if(!strcmp(nfc->dev->dev_name, "")) { set_random_name(nfc->text_store, sizeof(nfc->text_store)); dev_name_empty = true; } else { - nfc_text_store_set(nfc, nfc->dev.dev_name); + nfc_text_store_set(nfc, nfc->dev->dev_name); } text_input_set_header_text(text_input, "Name the card"); text_input_set_result_callback( @@ -37,14 +37,14 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SCENE_SAVE_NAME_CUSTOM_EVENT) { - if(strcmp(nfc->dev.dev_name, "")) { - nfc_device_delete(&nfc->dev); + if(strcmp(nfc->dev->dev_name, "")) { + nfc_device_delete(nfc->dev); } if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetUid)) { - nfc->dev.dev_data.nfc_data = nfc->dev_edit_data; + nfc->dev->dev_data.nfc_data = nfc->dev_edit_data; } - strlcpy(nfc->dev.dev_name, nfc->text_store, strlen(nfc->text_store) + 1); - if(nfc_device_save(&nfc->dev, nfc->text_store)) { + strlcpy(nfc->dev->dev_name, nfc->text_store, strlen(nfc->text_store) + 1); + if(nfc_device_save(nfc->dev, nfc->text_store)) { scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess); return true; } else { diff --git a/applications/nfc/scenes/nfc_scene_saved_menu.c b/applications/nfc/scenes/nfc_scene_saved_menu.c index a8e2ce7f..ea38ce3d 100755 --- a/applications/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/nfc/scenes/nfc_scene_saved_menu.c @@ -18,7 +18,7 @@ void nfc_scene_saved_menu_on_enter(void* context) { Nfc* nfc = (Nfc*)context; Submenu* submenu = nfc->submenu; - if(nfc->dev.format != NfcDeviceSaveFormatBankCard) { + if(nfc->dev->format != NfcDeviceSaveFormatBankCard) { submenu_add_item( submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc); } @@ -30,7 +30,7 @@ void nfc_scene_saved_menu_on_enter(void* context) { submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc); submenu_set_selected_item( nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu)); - if(nfc->dev.shadow_file_exist) { + if(nfc->dev->shadow_file_exist) { submenu_add_item( submenu, "Restore original", @@ -49,7 +49,7 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, event.event); if(event.event == SubmenuIndexEmulate) { - if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) { + if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl); } else { scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); @@ -65,7 +65,7 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo); consumed = true; } else if(event.event == SubmenuIndexRestoreOriginal) { - if(!nfc_device_restore(&nfc->dev)) { + if(!nfc_device_restore(nfc->dev)) { scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneStart); } else { diff --git a/applications/nfc/scenes/nfc_scene_set_atqa.c b/applications/nfc/scenes/nfc_scene_set_atqa.c index 7936880c..1c682f18 100755 --- a/applications/nfc/scenes/nfc_scene_set_atqa.c +++ b/applications/nfc/scenes/nfc_scene_set_atqa.c @@ -19,7 +19,7 @@ void nfc_scene_set_atqa_on_enter(void* context) { nfc_scene_set_atqa_byte_input_callback, NULL, nfc, - nfc->dev.dev_data.nfc_data.atqa, + nfc->dev->dev_data.nfc_data.atqa, 2); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput); } diff --git a/applications/nfc/scenes/nfc_scene_set_sak.c b/applications/nfc/scenes/nfc_scene_set_sak.c index 5df999d0..edeb27a9 100755 --- a/applications/nfc/scenes/nfc_scene_set_sak.c +++ b/applications/nfc/scenes/nfc_scene_set_sak.c @@ -19,7 +19,7 @@ void nfc_scene_set_sak_on_enter(void* context) { nfc_scene_set_sak_byte_input_callback, NULL, nfc, - &nfc->dev.dev_data.nfc_data.sak, + &nfc->dev->dev_data.nfc_data.sak, 1); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput); } diff --git a/applications/nfc/scenes/nfc_scene_set_type.c b/applications/nfc/scenes/nfc_scene_set_type.c index badab0c0..66eafe83 100755 --- a/applications/nfc/scenes/nfc_scene_set_type.c +++ b/applications/nfc/scenes/nfc_scene_set_type.c @@ -15,7 +15,7 @@ void nfc_scene_set_type_on_enter(void* context) { Nfc* nfc = (Nfc*)context; Submenu* submenu = nfc->submenu; // Clear device name - nfc_device_set_name(&nfc->dev, ""); + nfc_device_set_name(nfc->dev, ""); submenu_add_item( submenu, "NFC-A 7-bytes UID", SubmenuIndexNFCA7, nfc_scene_set_type_submenu_callback, nfc); submenu_add_item( @@ -28,13 +28,13 @@ bool nfc_scene_set_type_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexNFCA7) { - nfc->dev.dev_data.nfc_data.uid_len = 7; - nfc->dev.format = NfcDeviceSaveFormatUid; + nfc->dev->dev_data.nfc_data.uid_len = 7; + nfc->dev->format = NfcDeviceSaveFormatUid; scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak); return true; } else if(event.event == SubmenuIndexNFCA4) { - nfc->dev.dev_data.nfc_data.uid_len = 4; - nfc->dev.format = NfcDeviceSaveFormatUid; + nfc->dev->dev_data.nfc_data.uid_len = 4; + nfc->dev->format = NfcDeviceSaveFormatUid; scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak); return true; } diff --git a/applications/nfc/scenes/nfc_scene_set_uid.c b/applications/nfc/scenes/nfc_scene_set_uid.c index 7ecfbf32..5d179f77 100755 --- a/applications/nfc/scenes/nfc_scene_set_uid.c +++ b/applications/nfc/scenes/nfc_scene_set_uid.c @@ -14,7 +14,7 @@ void nfc_scene_set_uid_on_enter(void* context) { // Setup view ByteInput* byte_input = nfc->byte_input; byte_input_set_header_text(byte_input, "Enter uid in hex"); - nfc->dev_edit_data = nfc->dev.dev_data.nfc_data; + nfc->dev_edit_data = nfc->dev->dev_data.nfc_data; byte_input_set_result_callback( byte_input, nfc_scene_set_uid_byte_input_callback, diff --git a/applications/nfc/scenes/nfc_scene_start.c b/applications/nfc/scenes/nfc_scene_start.c index cdf7dbe2..bfeb494b 100755 --- a/applications/nfc/scenes/nfc_scene_start.c +++ b/applications/nfc/scenes/nfc_scene_start.c @@ -34,7 +34,7 @@ void nfc_scene_start_on_enter(void* context) { submenu_set_selected_item( submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneStart)); - nfc_device_clear(&nfc->dev); + nfc_device_clear(nfc->dev); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } diff --git a/applications/nfc/views/bank_card.c b/applications/nfc/views/bank_card.c index 483491d6..07b4db58 100755 --- a/applications/nfc/views/bank_card.c +++ b/applications/nfc/views/bank_card.c @@ -67,42 +67,14 @@ void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year) { bank_card->widget, 122, 54, AlignRight, AlignBottom, FontSecondary, exp_date_str); } -void bank_card_set_country_name(BankCard* bank_card, uint16_t country_code) { +void bank_card_set_country_name(BankCard* bank_card, const char* country_name) { furi_assert(bank_card); - string_t country_name; - string_init(country_name); - if(nfc_emv_parser_get_country_name(country_code, country_name)) { - string_t disp_country; - string_init_printf(disp_country, "Reg:%s", country_name); - widget_add_string_element( - bank_card->widget, - 120, - 18, - AlignRight, - AlignTop, - FontSecondary, - string_get_cstr(disp_country)); - string_clear(disp_country); - } - string_clear(country_name); + widget_add_string_element( + bank_card->widget, 120, 18, AlignRight, AlignTop, FontSecondary, country_name); } -void bank_card_set_currency_name(BankCard* bank_card, uint16_t currency_code) { +void bank_card_set_currency_name(BankCard* bank_card, const char* currency_name) { furi_assert(bank_card); - string_t currency_name; - string_init(currency_name); - if(nfc_emv_parser_get_currency_name(currency_code, currency_name)) { - string_t disp_currency; - string_init_printf(disp_currency, "Cur:%s", currency_name); - widget_add_string_element( - bank_card->widget, - 31, - 18, - AlignLeft, - AlignTop, - FontSecondary, - string_get_cstr(disp_currency)); - string_clear(disp_currency); - } - string_clear(currency_name); + widget_add_string_element( + bank_card->widget, 31, 18, AlignLeft, AlignTop, FontSecondary, currency_name); } diff --git a/applications/nfc/views/bank_card.h b/applications/nfc/views/bank_card.h index a4342856..628d9deb 100644 --- a/applications/nfc/views/bank_card.h +++ b/applications/nfc/views/bank_card.h @@ -21,6 +21,6 @@ void bank_card_set_number(BankCard* bank_card, uint8_t* number, uint8_t len); void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year); -void bank_card_set_country_name(BankCard* bank_card, uint16_t country_code); +void bank_card_set_country_name(BankCard* bank_card, const char* country_name); -void bank_card_set_currency_name(BankCard* bank_card, uint16_t currency_code); +void bank_card_set_currency_name(BankCard* bank_card, const char* currency_name); diff --git a/applications/notification/notification-app.c b/applications/notification/notification-app.c index 3912cf62..62a58ff6 100644 --- a/applications/notification/notification-app.c +++ b/applications/notification/notification-app.c @@ -5,6 +5,8 @@ #include "notification-messages.h" #include "notification-app.h" +#define TAG "NotificationSrv" + static const uint8_t minimal_delay = 100; static const uint8_t led_off_values[NOTIFICATION_LED_COUNT] = {0x00, 0x00, 0x00}; @@ -314,7 +316,7 @@ static bool notification_load_settings(NotificationApp* app) { File* file = storage_file_alloc(furi_record_open("storage")); const size_t settings_size = sizeof(NotificationSettings); - FURI_LOG_I("notification", "loading settings from \"%s\"", NOTIFICATION_SETTINGS_PATH); + FURI_LOG_I(TAG, "loading settings from \"%s\"", NOTIFICATION_SETTINGS_PATH); bool fs_result = storage_file_open(file, NOTIFICATION_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING); @@ -327,21 +329,18 @@ static bool notification_load_settings(NotificationApp* app) { } if(fs_result) { - FURI_LOG_I("notification", "load success"); + FURI_LOG_I(TAG, "load success"); if(settings.version != NOTIFICATION_SETTINGS_VERSION) { FURI_LOG_E( - "notification", - "version(%d != %d) mismatch", - settings.version, - NOTIFICATION_SETTINGS_VERSION); + TAG, "version(%d != %d) mismatch", settings.version, NOTIFICATION_SETTINGS_VERSION); } else { osKernelLock(); memcpy(&app->settings, &settings, settings_size); osKernelUnlock(); } } else { - FURI_LOG_E("notification", "load failed, %s", storage_file_get_error_desc(file)); + FURI_LOG_E(TAG, "load failed, %s", storage_file_get_error_desc(file)); } storage_file_close(file); @@ -356,7 +355,7 @@ static bool notification_save_settings(NotificationApp* app) { File* file = storage_file_alloc(furi_record_open("storage")); const size_t settings_size = sizeof(NotificationSettings); - FURI_LOG_I("notification", "saving settings to \"%s\"", NOTIFICATION_SETTINGS_PATH); + FURI_LOG_I(TAG, "saving settings to \"%s\"", NOTIFICATION_SETTINGS_PATH); osKernelLock(); memcpy(&settings, &app->settings, settings_size); @@ -374,9 +373,9 @@ static bool notification_save_settings(NotificationApp* app) { } if(fs_result) { - FURI_LOG_I("notification", "save success"); + FURI_LOG_I(TAG, "save success"); } else { - FURI_LOG_E("notification", "save failed, %s", storage_file_get_error_desc(file)); + FURI_LOG_E(TAG, "save failed, %s", storage_file_get_error_desc(file)); } storage_file_close(file); diff --git a/applications/rpc/rpc.c b/applications/rpc/rpc.c index 80355e5e..123f1faa 100644 --- a/applications/rpc/rpc.c +++ b/applications/rpc/rpc.c @@ -9,6 +9,7 @@ #include #include #include + #include #include #include @@ -16,14 +17,12 @@ #include #include -#define RPC_TAG "RPC" +#define TAG "RpcSrv" #define RPC_EVENT_NEW_DATA (1 << 0) #define RPC_EVENT_DISCONNECT (1 << 1) #define RPC_EVENTS_ALL (RPC_EVENT_DISCONNECT | RPC_EVENT_NEW_DATA) -#define DEBUG_PRINT 0 - DICT_DEF2(RpcHandlerDict, pb_size_t, M_DEFAULT_OPLIST, RpcHandler, M_POD_OPLIST) typedef struct { @@ -53,6 +52,7 @@ static RpcSystemCallbacks rpc_systems[] = { struct RpcSession { RpcSendBytesCallback send_bytes_callback; + RpcBufferIsEmptyCallback buffer_is_empty_callback; RpcSessionClosedCallback closed_callback; void* context; osMutexId_t callbacks_mutex; @@ -263,6 +263,7 @@ void rpc_print_message(const PB_Main* message) { size_t msg_file_count = message->content.storage_list_response.file_count; string_cat_printf(str, "\tlist_response {\r\n"); rpc_sprintf_msg_file(str, "\t\t", msg_file, msg_file_count); + break; } case PB_Main_gui_start_screen_stream_request_tag: string_cat_printf(str, "\tstart_screen_stream {\r\n"); @@ -270,8 +271,8 @@ void rpc_print_message(const PB_Main* message) { case PB_Main_gui_stop_screen_stream_request_tag: string_cat_printf(str, "\tstop_screen_stream {\r\n"); break; - case PB_Main_gui_screen_stream_frame_tag: - string_cat_printf(str, "\tscreen_stream_frame {\r\n"); + case PB_Main_gui_screen_frame_tag: + string_cat_printf(str, "\tscreen_frame {\r\n"); break; case PB_Main_gui_send_input_event_request_tag: string_cat_printf(str, "\tsend_input_event {\r\n"); @@ -280,6 +281,12 @@ void rpc_print_message(const PB_Main* message) { string_cat_printf( str, "\t\type: %d\r\n", message->content.gui_send_input_event_request.type); break; + case PB_Main_gui_start_virtual_display_request_tag: + string_cat_printf(str, "\tstart_virtual_display {\r\n"); + break; + case PB_Main_gui_stop_virtual_display_request_tag: + string_cat_printf(str, "\tstop_virtual_display {\r\n"); + break; } string_cat_printf(str, "\t}\r\n}\r\n"); printf("%s", string_get_cstr(str)); @@ -292,7 +299,7 @@ static Rpc* rpc_alloc(void) { rpc->busy_mutex = osMutexNew(NULL); rpc->busy = false; rpc->events = osEventFlagsNew(NULL); - rpc->stream = xStreamBufferCreate(256, 1); + rpc->stream = xStreamBufferCreate(RPC_BUFFER_SIZE, 1); rpc->decoded_message = furi_alloc(sizeof(PB_Main)); rpc->decoded_message->cb_content.funcs.decode = content_callback; @@ -334,7 +341,7 @@ RpcSession* rpc_session_open(Rpc* rpc) { }; rpc_add_handler(rpc, PB_Main_stop_session_tag, &rpc_handler); - FURI_LOG_D(RPC_TAG, "Session started\r\n"); + FURI_LOG_D(TAG, "Session started\r\n"); } return result ? &rpc->session : NULL; /* support 1 open session for now */ @@ -365,6 +372,7 @@ static void rpc_free_session(RpcSession* session) { session->context = NULL; session->closed_callback = NULL; session->send_bytes_callback = NULL; + session->buffer_is_empty_callback = NULL; } void rpc_session_set_context(RpcSession* session, void* context) { @@ -397,6 +405,18 @@ void rpc_session_set_send_bytes_callback(RpcSession* session, RpcSendBytesCallba osMutexRelease(session->callbacks_mutex); } +void rpc_session_set_buffer_is_empty_callback( + RpcSession* session, + RpcBufferIsEmptyCallback callback) { + furi_assert(session); + furi_assert(callback); + furi_assert(session->rpc->busy); + + osMutexAcquire(session->callbacks_mutex, osWaitForever); + session->buffer_is_empty_callback = callback; + osMutexRelease(session->callbacks_mutex); +} + /* Doesn't forbid using rpc_feed_bytes() after session close - it's safe. * Because any bytes received in buffer will be flushed before next session. * If bytes get into stream buffer before it's get epmtified and this @@ -415,6 +435,12 @@ size_t return bytes_sent; } +size_t rpc_session_get_available_size(RpcSession* session) { + furi_assert(session); + Rpc* rpc = session->rpc; + return xStreamBufferSpacesAvailable(rpc->stream); +} + bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) { Rpc* rpc = istream->state; uint32_t flags = 0; @@ -425,6 +451,11 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) { while(1) { bytes_received += xStreamBufferReceive(rpc->stream, buf + bytes_received, count - bytes_received, 0); + if(xStreamBufferIsEmpty(rpc->stream)) { + if(rpc->session.buffer_is_empty_callback) { + rpc->session.buffer_is_empty_callback(rpc->session.context); + } + } if(count == bytes_received) { break; } else { @@ -443,7 +474,7 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) { } } -#if DEBUG_PRINT +#if SRV_RPC_DEBUG rpc_print_data("INPUT", buf, bytes_received); #endif @@ -456,8 +487,8 @@ void rpc_send_and_release(Rpc* rpc, PB_Main* message) { RpcSession* session = &rpc->session; pb_ostream_t ostream = PB_OSTREAM_SIZING; -#if DEBUG_PRINT - FURI_LOG_I(RPC_TAG, "OUTPUT:"); +#if SRV_RPC_DEBUG + FURI_LOG_I(TAG, "OUTPUT:"); rpc_print_message(message); #endif @@ -469,7 +500,7 @@ void rpc_send_and_release(Rpc* rpc, PB_Main* message) { pb_encode_ex(&ostream, &PB_Main_msg, message, PB_ENCODE_DELIMITED); -#if DEBUG_PRINT +#if SRV_RPC_DEBUG rpc_print_data("OUTPUT", buffer, ostream.bytes_written); #endif @@ -510,12 +541,12 @@ int32_t rpc_srv(void* p) { .callback = rpc_pb_stream_read, .state = rpc, .errmsg = NULL, - .bytes_left = 1024, /* max incoming message size */ + .bytes_left = RPC_MAX_MESSAGE_SIZE, /* max incoming message size */ }; if(pb_decode_ex(&istream, &PB_Main_msg, rpc->decoded_message, PB_DECODE_DELIMITED)) { -#if DEBUG_PRINT - FURI_LOG_I(RPC_TAG, "INPUT:"); +#if SRV_RPC_DEBUG + FURI_LOG_I(TAG, "INPUT:"); rpc_print_message(rpc->decoded_message); #endif RpcHandler* handler = @@ -524,20 +555,19 @@ int32_t rpc_srv(void* p) { if(handler && handler->message_handler) { handler->message_handler(rpc->decoded_message, handler->context); } else if(!handler && !rpc->session.terminate) { - FURI_LOG_E( - RPC_TAG, "Unhandled message, tag: %d", rpc->decoded_message->which_content); + FURI_LOG_E(TAG, "Unhandled message, tag: %d", rpc->decoded_message->which_content); } } else { xStreamBufferReset(rpc->stream); if(!rpc->session.terminate) { - FURI_LOG_E(RPC_TAG, "Decode failed, error: \'%.128s\'", PB_GET_ERROR(&istream)); + FURI_LOG_E(TAG, "Decode failed, error: \'%.128s\'", PB_GET_ERROR(&istream)); } } pb_release(&PB_Main_msg, rpc->decoded_message); if(rpc->session.terminate) { - FURI_LOG_D(RPC_TAG, "Session terminated"); + FURI_LOG_D(TAG, "Session terminated"); osEventFlagsClear(rpc->events, RPC_EVENTS_ALL); rpc_free_session(&rpc->session); rpc->busy = false; diff --git a/applications/rpc/rpc.h b/applications/rpc/rpc.h old mode 100644 new mode 100755 index 29e37773..61e315ba --- a/applications/rpc/rpc.h +++ b/applications/rpc/rpc.h @@ -4,6 +4,9 @@ #include #include "cmsis_os.h" +#define RPC_BUFFER_SIZE (1024) +#define RPC_MAX_MESSAGE_SIZE (1536) + /** Rpc interface. Used for opening session only. */ typedef struct Rpc Rpc; /** Rpc session interface */ @@ -11,6 +14,8 @@ typedef struct RpcSession RpcSession; /** Callback to send to client any data (e.g. response to command) */ typedef void (*RpcSendBytesCallback)(void* context, uint8_t* bytes, size_t bytes_len); +/** Callback to notify client that buffer is empty */ +typedef void (*RpcBufferIsEmptyCallback)(void* context); /** Callback to notify transport layer that close_session command * is received. Any other actions lays on transport layer. * No destruction or session close preformed. */ @@ -59,6 +64,15 @@ void rpc_session_set_context(RpcSession* session, void* context); */ void rpc_session_set_send_bytes_callback(RpcSession* session, RpcSendBytesCallback callback); +/** Set callback to notify that buffer is empty + * + * @param session pointer to RpcSession descriptor + * @param callback callback to notify client that buffer is empty (can be NULL) + */ +void rpc_session_set_buffer_is_empty_callback( + RpcSession* session, + RpcBufferIsEmptyCallback callback); + /** Set callback to be called when RPC command to close session is received * WARN: It's forbidden to call RPC API within RpcSessionClosedCallback * @@ -77,3 +91,11 @@ void rpc_session_set_close_callback(RpcSession* session, RpcSessionClosedCallbac * @return actually consumed bytes */ size_t rpc_session_feed(RpcSession* session, uint8_t* buffer, size_t size, TickType_t timeout); + +/** Get available size of RPC buffer + * + * @param session pointer to RpcSession descriptor + * + * @return bytes available in buffer + */ +size_t rpc_session_get_available_size(RpcSession* session); diff --git a/applications/rpc/rpc_cli.c b/applications/rpc/rpc_cli.c index 853e9dd3..373217b9 100644 --- a/applications/rpc/rpc_cli.c +++ b/applications/rpc/rpc_cli.c @@ -1,14 +1,14 @@ #include #include #include -#include +#include typedef struct { Cli* cli; bool session_close_request; } CliRpc; -#define CLI_READ_BUFFER_SIZE 100 +#define CLI_READ_BUFFER_SIZE 64 static void rpc_send_bytes_callback(void* context, uint8_t* bytes, size_t bytes_len) { furi_assert(context); @@ -50,7 +50,8 @@ void rpc_cli_command_start_session(Cli* cli, string_t args, void* context) { } if(size_received) { - rpc_session_feed(rpc_session, buffer, size_received, 3000); + furi_assert( + rpc_session_feed(rpc_session, buffer, size_received, 3000) == size_received); } } diff --git a/applications/rpc/rpc_gui.c b/applications/rpc/rpc_gui.c index 10a0afd9..6e9cfb08 100644 --- a/applications/rpc/rpc_gui.c +++ b/applications/rpc/rpc_gui.c @@ -3,12 +3,17 @@ #include "gui.pb.h" #include +#define TAG "RpcGui" + typedef struct { Rpc* rpc; Gui* gui; + ViewPort* virtual_display_view_port; + uint8_t* virtual_display_buffer; + bool virtual_display_not_empty; } RpcGuiSystem; -void rpc_system_gui_screen_frame_callback(uint8_t* data, size_t size, void* context) { +void rpc_system_gui_screen_stream_frame_callback(uint8_t* data, size_t size, void* context) { furi_assert(data); furi_assert(size == 1024); furi_assert(context); @@ -17,11 +22,11 @@ void rpc_system_gui_screen_frame_callback(uint8_t* data, size_t size, void* cont PB_Main* frame = furi_alloc(sizeof(PB_Main)); - frame->which_content = PB_Main_gui_screen_stream_frame_tag; + frame->which_content = PB_Main_gui_screen_frame_tag; frame->command_status = PB_CommandStatus_OK; - frame->content.gui_screen_stream_frame.data = furi_alloc(PB_BYTES_ARRAY_T_ALLOCSIZE(size)); - uint8_t* buffer = frame->content.gui_screen_stream_frame.data->bytes; - uint16_t* frame_size_msg = &frame->content.gui_screen_stream_frame.data->size; + frame->content.gui_screen_frame.data = furi_alloc(PB_BYTES_ARRAY_T_ALLOCSIZE(size)); + uint8_t* buffer = frame->content.gui_screen_frame.data->bytes; + uint16_t* frame_size_msg = &frame->content.gui_screen_frame.data->size; *frame_size_msg = size; memcpy(buffer, data, size); @@ -37,7 +42,8 @@ void rpc_system_gui_start_screen_stream_process(const PB_Main* request, void* co rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK); - gui_set_framebuffer_callback(rpc_gui->gui, rpc_system_gui_screen_frame_callback, context); + gui_set_framebuffer_callback( + rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context); } void rpc_system_gui_stop_screen_stream_process(const PB_Main* request, void* context) { @@ -45,9 +51,9 @@ void rpc_system_gui_stop_screen_stream_process(const PB_Main* request, void* con furi_assert(context); RpcGuiSystem* rpc_gui = context; - rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK); - gui_set_framebuffer_callback(rpc_gui->gui, NULL, NULL); + + rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK); } void rpc_system_gui_send_input_event_request_process(const PB_Main* request, void* context) { @@ -120,6 +126,88 @@ void rpc_system_gui_send_input_event_request_process(const PB_Main* request, voi rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK); } +static void rpc_system_gui_virtual_display_render_callback(Canvas* canvas, void* context) { + furi_assert(canvas); + furi_assert(context); + RpcGuiSystem* rpc_gui = context; + + if(!rpc_gui->virtual_display_not_empty) { + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, 64, 20, AlignCenter, AlignCenter, "Virtual Display"); + canvas_draw_str_aligned(canvas, 64, 36, AlignCenter, AlignCenter, "Waiting for frames..."); + return; + } + + canvas_draw_xbm(canvas, 0, 0, canvas->width, canvas->height, rpc_gui->virtual_display_buffer); +} + +void rpc_system_gui_start_virtual_display_process(const PB_Main* request, void* context) { + furi_assert(request); + furi_assert(context); + RpcGuiSystem* rpc_gui = context; + + if(rpc_gui->virtual_display_view_port) { + rpc_send_and_release_empty( + rpc_gui->rpc, + request->command_id, + PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_ALREADY_STARTED); + return; + } + + // TODO: consider refactoring + // Using display framebuffer size as an XBM buffer size is like comparing apples and oranges + // Glad they both are 1024 for now + size_t buffer_size = canvas_get_buffer_size(rpc_gui->gui->canvas); + rpc_gui->virtual_display_buffer = furi_alloc(buffer_size); + rpc_gui->virtual_display_view_port = view_port_alloc(); + view_port_draw_callback_set( + rpc_gui->virtual_display_view_port, + rpc_system_gui_virtual_display_render_callback, + rpc_gui); + gui_add_view_port(rpc_gui->gui, rpc_gui->virtual_display_view_port, GuiLayerFullscreen); + + rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK); +} + +void rpc_system_gui_stop_virtual_display_process(const PB_Main* request, void* context) { + furi_assert(request); + furi_assert(context); + RpcGuiSystem* rpc_gui = context; + + if(!rpc_gui->virtual_display_view_port) { + rpc_send_and_release_empty( + rpc_gui->rpc, request->command_id, PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_NOT_STARTED); + return; + } + + gui_remove_view_port(rpc_gui->gui, rpc_gui->virtual_display_view_port); + view_port_free(rpc_gui->virtual_display_view_port); + free(rpc_gui->virtual_display_buffer); + rpc_gui->virtual_display_view_port = NULL; + rpc_gui->virtual_display_not_empty = false; + + rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK); +} + +void rpc_system_gui_virtual_display_frame_process(const PB_Main* request, void* context) { + furi_assert(request); + furi_assert(context); + RpcGuiSystem* rpc_gui = context; + + if(!rpc_gui->virtual_display_view_port) { + FURI_LOG_W(TAG, "Virtual display is not started, ignoring incoming frame packet"); + return; + } + + size_t buffer_size = canvas_get_buffer_size(rpc_gui->gui->canvas); + memcpy( + rpc_gui->virtual_display_buffer, + request->content.gui_screen_frame.data->bytes, + buffer_size); + rpc_gui->virtual_display_not_empty = true; + view_port_update(rpc_gui->virtual_display_view_port); +} + void* rpc_system_gui_alloc(Rpc* rpc) { furi_assert(rpc); @@ -142,6 +230,15 @@ void* rpc_system_gui_alloc(Rpc* rpc) { rpc_handler.message_handler = rpc_system_gui_send_input_event_request_process; rpc_add_handler(rpc, PB_Main_gui_send_input_event_request_tag, &rpc_handler); + rpc_handler.message_handler = rpc_system_gui_start_virtual_display_process; + rpc_add_handler(rpc, PB_Main_gui_start_virtual_display_request_tag, &rpc_handler); + + rpc_handler.message_handler = rpc_system_gui_stop_virtual_display_process; + rpc_add_handler(rpc, PB_Main_gui_stop_virtual_display_request_tag, &rpc_handler); + + rpc_handler.message_handler = rpc_system_gui_virtual_display_frame_process; + rpc_add_handler(rpc, PB_Main_gui_screen_frame_tag, &rpc_handler); + return rpc_gui; } @@ -149,6 +246,15 @@ void rpc_system_gui_free(void* ctx) { furi_assert(ctx); RpcGuiSystem* rpc_gui = ctx; furi_assert(rpc_gui->gui); + + if(rpc_gui->virtual_display_view_port) { + gui_remove_view_port(rpc_gui->gui, rpc_gui->virtual_display_view_port); + view_port_free(rpc_gui->virtual_display_view_port); + free(rpc_gui->virtual_display_buffer); + rpc_gui->virtual_display_view_port = NULL; + rpc_gui->virtual_display_not_empty = false; + } + gui_set_framebuffer_callback(rpc_gui->gui, NULL, NULL); furi_record_close("gui"); free(rpc_gui); diff --git a/applications/storage/storage-external-api.c b/applications/storage/storage-external-api.c index 7f275894..ae798ecb 100644 --- a/applications/storage/storage-external-api.c +++ b/applications/storage/storage-external-api.c @@ -463,3 +463,28 @@ bool storage_simply_mkdir(Storage* storage, const char* path) { result = storage_common_mkdir(storage, path); return result == FSE_OK || result == FSE_EXIST; } + +void storage_get_next_filename( + Storage* storage, + const char* dirname, + const char* filename, + const char* fileextension, + string_t nextfilename) { + string_t temp_str; + uint16_t num = 0; + + string_init_printf(temp_str, "%s/%s%s", dirname, filename, fileextension); + + while(storage_common_stat(storage, string_get_cstr(temp_str), NULL) == FSE_OK) { + num++; + string_printf(temp_str, "%s/%s%d%s", dirname, filename, num, fileextension); + } + + if(num) { + string_printf(nextfilename, "%s%d", filename, num); + } else { + string_printf(nextfilename, "%s", filename); + } + + string_clear(temp_str); +} diff --git a/applications/storage/storage-test-app.c b/applications/storage/storage-test-app.c index 022181a5..1c4e1915 100644 --- a/applications/storage/storage-test-app.c +++ b/applications/storage/storage-test-app.c @@ -2,7 +2,7 @@ #include #include -#define TAG "storage-test" +#define TAG "StorageTest" #define BYTES_COUNT 16 #define TEST_STRING "TestDataStringProvidedByDiceRoll" #define SEEK_OFFSET_FROM_START 10 diff --git a/applications/storage/storage.h b/applications/storage/storage.h index 9351e155..fc7ac665 100644 --- a/applications/storage/storage.h +++ b/applications/storage/storage.h @@ -262,6 +262,22 @@ bool storage_simply_remove_recursive(Storage* storage, const char* path); */ bool storage_simply_mkdir(Storage* storage, const char* path); +/** + * @brief Get next free filename. + * + * @param storage + * @param dirname + * @param filename + * @param fileextension + * @param nextfilename return name + */ +void storage_get_next_filename( + Storage* storage, + const char* dirname, + const char* filename, + const char* fileextension, + string_t nextfilename); + #ifdef __cplusplus } #endif diff --git a/applications/storage/storages/storage-ext.c b/applications/storage/storages/storage-ext.c index a434c2d8..51de7612 100644 --- a/applications/storage/storages/storage-ext.c +++ b/applications/storage/storages/storage-ext.c @@ -10,7 +10,7 @@ typedef DIR SDDir; typedef FILINFO SDFileInfo; typedef FRESULT SDError; -#define TAG "storage-ext" +#define TAG "StorageExt" #define STORAGE_PATH "/ext" /********************* Definitions ********************/ diff --git a/applications/storage/storages/storage-int.c b/applications/storage/storages/storage-int.c index 4a1dca7c..69ffe15e 100644 --- a/applications/storage/storages/storage-int.c +++ b/applications/storage/storages/storage-int.c @@ -2,7 +2,7 @@ #include #include -#define TAG "storage-int" +#define TAG "StorageInt" #define STORAGE_PATH "/int" typedef struct { @@ -121,7 +121,7 @@ static int storage_int_device_erase(const struct lfs_config* c, lfs_block_t bloc FURI_LOG_D(TAG, "Device erase: page %d, translated page: %x", block, page); - if(furi_hal_flash_erase(page, 1)) { + if(furi_hal_flash_erase(page)) { return 0; } else { return -1; diff --git a/applications/subghz/helpers/subghz_frequency_analyzer_worker.c b/applications/subghz/helpers/subghz_frequency_analyzer_worker.c index 5c7199b6..ddf557a6 100644 --- a/applications/subghz/helpers/subghz_frequency_analyzer_worker.c +++ b/applications/subghz/helpers/subghz_frequency_analyzer_worker.c @@ -145,7 +145,7 @@ SubGhzFrequencyAnalyzerWorker* subghz_frequency_analyzer_worker_alloc() { SubGhzFrequencyAnalyzerWorker* instance = furi_alloc(sizeof(SubGhzFrequencyAnalyzerWorker)); instance->thread = furi_thread_alloc(); - furi_thread_set_name(instance->thread, "subghz_frequency_analyzer_worker"); + furi_thread_set_name(instance->thread, "SubghzFAWorker"); furi_thread_set_stack_size(instance->thread, 2048); furi_thread_set_context(instance->thread, instance); furi_thread_set_callback(instance->thread, subghz_frequency_analyzer_worker_thread); diff --git a/applications/subghz/scenes/subghz_scene_delete.c b/applications/subghz/scenes/subghz_scene_delete.c index e79e3a6d..eb8a2217 100644 --- a/applications/subghz/scenes/subghz_scene_delete.c +++ b/applications/subghz/scenes/subghz_scene_delete.c @@ -11,33 +11,33 @@ void subghz_scene_delete_callback(GuiButtonType result, InputType type, void* co void subghz_scene_delete_on_enter(void* context) { SubGhz* subghz = context; - - char buffer_str[16]; - snprintf( - buffer_str, - sizeof(buffer_str), - "%03ld.%02ld", - subghz->txrx->frequency / 1000000 % 1000, - subghz->txrx->frequency / 10000 % 100); - widget_add_string_element( - subghz->widget, 78, 0, AlignLeft, AlignTop, FontSecondary, buffer_str); - if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async || - subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) { - snprintf(buffer_str, sizeof(buffer_str), "AM"); - } else if( - subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async || - subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) { - snprintf(buffer_str, sizeof(buffer_str), "FM"); - } else { - furi_crash(NULL); - } - widget_add_string_element( - subghz->widget, 113, 0, AlignLeft, AlignTop, FontSecondary, buffer_str); + string_t frequency_str; + string_t modulation_str; string_t text; + + string_init(frequency_str); + string_init(modulation_str); string_init(text); + + subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); + widget_add_string_element( + subghz->widget, 78, 0, AlignLeft, AlignTop, FontSecondary, string_get_cstr(frequency_str)); + + widget_add_string_element( + subghz->widget, + 113, + 0, + AlignLeft, + AlignTop, + FontSecondary, + string_get_cstr(modulation_str)); + subghz->txrx->protocol_result->to_string(subghz->txrx->protocol_result, text); widget_add_string_multiline_element( subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, string_get_cstr(text)); + + string_clear(frequency_str); + string_clear(modulation_str); string_clear(text); widget_add_button_element( @@ -50,7 +50,7 @@ bool subghz_scene_delete_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubghzCustomEventSceneDelete) { - memcpy(subghz->file_name_tmp, subghz->file_name, strlen(subghz->file_name)); + memcpy(subghz->file_name_tmp, subghz->file_name, strlen(subghz->file_name) + 1); if(subghz_delete_file(subghz)) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess); } else { diff --git a/applications/subghz/scenes/subghz_scene_read_raw.c b/applications/subghz/scenes/subghz_scene_read_raw.c index 6d4a72d1..7bf5576e 100644 --- a/applications/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/subghz/scenes/subghz_scene_read_raw.c @@ -6,27 +6,19 @@ static void subghz_scene_read_raw_update_statusbar(void* context) { furi_assert(context); SubGhz* subghz = context; - char frequency_str[20]; - char preset_str[10]; - snprintf( - frequency_str, - sizeof(frequency_str), - "%03ld.%02ld", - subghz->txrx->frequency / 1000000 % 1000, - subghz->txrx->frequency / 10000 % 100); - if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async || - subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) { - snprintf(preset_str, sizeof(preset_str), "AM"); - } else if( - subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async || - subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) { - snprintf(preset_str, sizeof(preset_str), "FM"); - } else { - furi_crash(NULL); - } + string_t frequency_str; + string_t modulation_str; - subghz_read_raw_add_data_statusbar(subghz->subghz_read_raw, frequency_str, preset_str); + string_init(frequency_str); + string_init(modulation_str); + + subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); + subghz_read_raw_add_data_statusbar( + subghz->subghz_read_raw, string_get_cstr(frequency_str), string_get_cstr(modulation_str)); + + string_clear(frequency_str); + string_clear(modulation_str); } void subghz_scene_read_raw_callback(SubghzCustomEvent event, void* context) { @@ -70,7 +62,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { subghz->txrx->preset = FuriHalSubGhzPresetOok650Async; subghz_protocol_raw_save_to_file_stop( (SubGhzProtocolRAW*)subghz->txrx->protocol_result); - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz->state_notifications = SubGhzNotificationStateIDLE; if(subghz->txrx->rx_key_state == SubGhzRxKeyStateAddKey) { subghz->txrx->rx_key_state = SubGhzRxKeyStateExit; @@ -95,7 +87,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { }; subghz_protocol_raw_save_to_file_stop( (SubGhzProtocolRAW*)subghz->txrx->protocol_result); - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz->state_notifications = SubGhzNotificationStateIDLE; subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey; @@ -106,17 +98,18 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { if(subghz->txrx->rx_key_state != SubGhzRxKeyStateIDLE) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving); } else { + subghz_get_preset_name(subghz, subghz->error_str); if(subghz_protocol_raw_save_to_file_init( (SubGhzProtocolRAW*)subghz->txrx->protocol_result, "Raw_temp", subghz->txrx->frequency, - subghz->txrx->preset)) { + string_get_cstr(subghz->error_str))) { if((subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) || (subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) { subghz_begin(subghz, subghz->txrx->preset); subghz_rx(subghz, subghz->txrx->frequency); } - subghz->state_notifications = NOTIFICATION_RX_STATE; + subghz->state_notifications = SubGhzNotificationStateRX; } else { string_set(subghz->error_str, "No SD card"); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); @@ -127,14 +120,14 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { break; case SubghzCustomEventViewReadRAWMore: if(strcmp( - subghz_protocol_get_last_file_name( + subghz_protocol_raw_get_last_file_name( (SubGhzProtocolRAW*)subghz->txrx->protocol_result), "")) { strlcpy( subghz->file_name, - subghz_protocol_get_last_file_name( + subghz_protocol_raw_get_last_file_name( (SubGhzProtocolRAW*)subghz->txrx->protocol_result), - strlen(subghz_protocol_get_last_file_name( + strlen(subghz_protocol_raw_get_last_file_name( (SubGhzProtocolRAW*)subghz->txrx->protocol_result)) + 1); //set the path to read the file @@ -145,7 +138,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { SUBGHZ_APP_PATH_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION); - subghz_protocol_set_last_file_name( + subghz_protocol_raw_set_last_file_name( (SubGhzProtocolRAW*)subghz->txrx->protocol_result, string_get_cstr(temp_str)); string_clear(temp_str); @@ -159,7 +152,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { } } else if(event.type == SceneManagerEventTypeTick) { switch(subghz->state_notifications) { - case NOTIFICATION_RX_STATE: + case SubGhzNotificationStateRX: notification_message(subghz->notifications, &sequence_blink_blue_10); subghz_read_raw_update_sample_write( subghz->subghz_read_raw, @@ -182,7 +175,7 @@ void subghz_scene_read_raw_on_exit(void* context) { subghz_rx_end(subghz); subghz_sleep(subghz); }; - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz->state_notifications = SubGhzNotificationStateIDLE; //Сallback restoration subghz_worker_set_pair_callback( diff --git a/applications/subghz/scenes/subghz_scene_receiver.c b/applications/subghz/scenes/subghz_scene_receiver.c index 107381c2..4e8a953f 100644 --- a/applications/subghz/scenes/subghz_scene_receiver.c +++ b/applications/subghz/scenes/subghz_scene_receiver.c @@ -3,33 +3,29 @@ static void subghz_scene_receiver_update_statusbar(void* context) { SubGhz* subghz = context; - char frequency_str[20]; - char preset_str[10]; string_t history_stat_str; string_init(history_stat_str); if(!subghz_history_get_text_space_left(subghz->txrx->history, history_stat_str)) { - snprintf( - frequency_str, - sizeof(frequency_str), - "%03ld.%02ld", - subghz->txrx->frequency / 1000000 % 1000, - subghz->txrx->frequency / 10000 % 100); - if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async || - subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) { - snprintf(preset_str, sizeof(preset_str), "AM"); - } else if( - subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async || - subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) { - snprintf(preset_str, sizeof(preset_str), "FM"); - } else { - furi_crash(NULL); - } + string_t frequency_str; + string_t modulation_str; + + string_init(frequency_str); + string_init(modulation_str); + + subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); + subghz_receiver_add_data_statusbar( - subghz->subghz_receiver, frequency_str, preset_str, string_get_cstr(history_stat_str)); + subghz->subghz_receiver, + string_get_cstr(frequency_str), + string_get_cstr(modulation_str), + string_get_cstr(history_stat_str)); + + string_clear(frequency_str); + string_clear(modulation_str); } else { subghz_receiver_add_data_statusbar( subghz->subghz_receiver, string_get_cstr(history_stat_str), "", ""); - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz->state_notifications = SubGhzNotificationStateIDLE; } string_clear(history_stat_str); } @@ -83,7 +79,7 @@ void subghz_scene_receiver_on_enter(void* context) { subghz_receiver_set_callback(subghz->subghz_receiver, subghz_scene_receiver_callback, subghz); subghz_parser_enable_dump(subghz->txrx->parser, subghz_scene_add_to_history_callback, subghz); - subghz->state_notifications = NOTIFICATION_RX_STATE; + subghz->state_notifications = SubGhzNotificationStateRX; if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { subghz_rx_end(subghz); }; @@ -104,7 +100,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { switch(event.event) { case SubghzCustomEventViewReceverBack: // Stop CC1101 Rx - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz->state_notifications = SubGhzNotificationStateIDLE; if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { subghz_rx_end(subghz); subghz_sleep(subghz); @@ -125,7 +121,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { return true; break; case SubghzCustomEventViewReceverConfig: - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz->state_notifications = SubGhzNotificationStateIDLE; subghz->txrx->idx_menu_chosen = subghz_receiver_get_idx_menu(subghz->subghz_receiver); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig); return true; @@ -140,7 +136,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { } switch(subghz->state_notifications) { - case NOTIFICATION_RX_STATE: + case SubGhzNotificationStateRX: notification_message(subghz->notifications, &sequence_blink_blue_10); break; default: diff --git a/applications/subghz/scenes/subghz_scene_receiver_info.c b/applications/subghz/scenes/subghz_scene_receiver_info.c index 1e9f100a..a8935a1c 100644 --- a/applications/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/subghz/scenes/subghz_scene_receiver_info.c @@ -40,35 +40,42 @@ void subghz_scene_receiver_info_on_enter(void* context) { SubGhz* subghz = context; if(subghz_scene_receiver_info_update_parser(subghz)) { - char buffer_str[16]; - snprintf( - buffer_str, - sizeof(buffer_str), - "%03ld.%02ld", - subghz->txrx->frequency / 1000000 % 1000, - subghz->txrx->frequency / 10000 % 100); - widget_add_string_element( - subghz->widget, 78, 0, AlignLeft, AlignTop, FontSecondary, buffer_str); - if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async || - subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) { - snprintf(buffer_str, sizeof(buffer_str), "AM"); - } else if( - subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async || - subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) { - snprintf(buffer_str, sizeof(buffer_str), "FM"); - } else { - furi_crash(NULL); - } - widget_add_string_element( - subghz->widget, 113, 0, AlignLeft, AlignTop, FontSecondary, buffer_str); + string_t frequency_str; + string_t modulation_str; string_t text; + + string_init(frequency_str); + string_init(modulation_str); string_init(text); + + subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); + widget_add_string_element( + subghz->widget, + 78, + 0, + AlignLeft, + AlignTop, + FontSecondary, + string_get_cstr(frequency_str)); + + widget_add_string_element( + subghz->widget, + 113, + 0, + AlignLeft, + AlignTop, + FontSecondary, + string_get_cstr(modulation_str)); + subghz->txrx->protocol_result->to_string(subghz->txrx->protocol_result, text); widget_add_string_multiline_element( subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, string_get_cstr(text)); + + string_clear(frequency_str); + string_clear(modulation_str); string_clear(text); - if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->to_save_string && + if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->to_save_file && strcmp(subghz->txrx->protocol_result->name, "KeeLoq")) { widget_add_button_element( subghz->widget, @@ -112,13 +119,13 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) if(!subghz_tx_start(subghz)) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx); } else { - subghz->state_notifications = NOTIFICATION_TX_STATE; + subghz->state_notifications = SubGhzNotificationStateTX; } } return true; } else if(event.event == SubghzCustomEventSceneReceiverInfoTxStop) { //CC1101 Stop Tx -> Start RX - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz->state_notifications = SubGhzNotificationStateIDLE; if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { subghz_tx_stop(subghz); } @@ -129,11 +136,11 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) if(subghz->txrx->hopper_state == SubGhzHopperStatePause) { subghz->txrx->hopper_state = SubGhzHopperStateRunnig; } - subghz->state_notifications = NOTIFICATION_RX_STATE; + subghz->state_notifications = SubGhzNotificationStateRX; return true; } else if(event.event == SubghzCustomEventSceneReceiverInfoSave) { //CC1101 Stop RX -> Save - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz->state_notifications = SubGhzNotificationStateIDLE; if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) { subghz->txrx->hopper_state = SubGhzHopperStateOFF; } @@ -144,7 +151,7 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) if(!subghz_scene_receiver_info_update_parser(subghz)) { return false; } - if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->to_save_string && + if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->to_save_file && strcmp(subghz->txrx->protocol_result->name, "KeeLoq")) { subghz_file_name_clear(subghz); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); @@ -156,10 +163,10 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) subghz_hopper_update(subghz); } switch(subghz->state_notifications) { - case NOTIFICATION_TX_STATE: + case SubGhzNotificationStateTX: notification_message(subghz->notifications, &sequence_blink_red_10); break; - case NOTIFICATION_RX_STATE: + case SubGhzNotificationStateRX: notification_message(subghz->notifications, &sequence_blink_blue_10); break; default: diff --git a/applications/subghz/scenes/subghz_scene_save_name.c b/applications/subghz/scenes/subghz_scene_save_name.c index 6cba3240..d448119c 100644 --- a/applications/subghz/scenes/subghz_scene_save_name.c +++ b/applications/subghz/scenes/subghz_scene_save_name.c @@ -19,7 +19,7 @@ void subghz_scene_save_name_on_enter(void* context) { set_random_name(subghz->file_name, sizeof(subghz->file_name)); dev_name_empty = true; } else { - memcpy(subghz->file_name_tmp, subghz->file_name, strlen(subghz->file_name)); + memcpy(subghz->file_name_tmp, subghz->file_name, strlen(subghz->file_name) + 1); if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAWMenu) == SubghzCustomEventManagerSet) { subghz_get_next_name_file(subghz); diff --git a/applications/subghz/scenes/subghz_scene_start.c b/applications/subghz/scenes/subghz_scene_start.c index fe37d7ae..3b5b5cd1 100644 --- a/applications/subghz/scenes/subghz_scene_start.c +++ b/applications/subghz/scenes/subghz_scene_start.c @@ -16,8 +16,8 @@ void subghz_scene_start_submenu_callback(void* context, uint32_t index) { void subghz_scene_start_on_enter(void* context) { SubGhz* subghz = context; - if(subghz->state_notifications == NOTIFICATION_STARTING_STATE) { - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + if(subghz->state_notifications == SubGhzNotificationStateStarting) { + subghz->state_notifications = SubGhzNotificationStateIDLE; } submenu_add_item( subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz); diff --git a/applications/subghz/scenes/subghz_scene_transmitter.c b/applications/subghz/scenes/subghz_scene_transmitter.c index 28d49397..16617589 100644 --- a/applications/subghz/scenes/subghz_scene_transmitter.c +++ b/applications/subghz/scenes/subghz_scene_transmitter.c @@ -13,9 +13,12 @@ bool subghz_scene_transmitter_update_data_show(void* context) { if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->get_upload_protocol) { string_t key_str; + string_t frequency_str; + string_t modulation_str; + string_init(key_str); - char frequency_str[10]; - char preset_str[6]; + string_init(frequency_str); + string_init(modulation_str); uint8_t show_button = 0; subghz->txrx->protocol_result->to_string(subghz->txrx->protocol_result, key_str); @@ -27,29 +30,17 @@ bool subghz_scene_transmitter_update_data_show(void* context) { } else { show_button = 1; } - snprintf( - frequency_str, - sizeof(frequency_str), - "%03ld.%02ld", - subghz->txrx->frequency / 1000000 % 1000, - subghz->txrx->frequency / 10000 % 100); - if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async || - subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) { - snprintf(preset_str, sizeof(preset_str), "AM"); - } else if( - subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async || - subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) { - snprintf(preset_str, sizeof(preset_str), "FM"); - } else { - furi_crash(NULL); - } + subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); subghz_transmitter_add_data_to_show( subghz->subghz_transmitter, string_get_cstr(key_str), - frequency_str, - preset_str, + string_get_cstr(frequency_str), + string_get_cstr(modulation_str), show_button); + + string_clear(frequency_str); + string_clear(modulation_str); string_clear(key_str); return true; @@ -67,7 +58,7 @@ void subghz_scene_transmitter_on_enter(void* context) { subghz_transmitter_set_callback( subghz->subghz_transmitter, subghz_scene_transmitter_callback, subghz); - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz->state_notifications = SubGhzNotificationStateIDLE; view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTransmitter); } @@ -75,7 +66,7 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubghzCustomEventViewTransmitterSendStart) { - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz->state_notifications = SubGhzNotificationStateIDLE; if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { subghz_rx_end(subghz); } @@ -84,20 +75,20 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { if(!subghz_tx_start(subghz)) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx); } else { - subghz->state_notifications = NOTIFICATION_TX_STATE; + subghz->state_notifications = SubGhzNotificationStateTX; subghz_scene_transmitter_update_data_show(subghz); } } return true; } else if(event.event == SubghzCustomEventViewTransmitterSendStop) { - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz->state_notifications = SubGhzNotificationStateIDLE; if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { subghz_tx_stop(subghz); subghz_sleep(subghz); } return true; } else if(event.event == SubghzCustomEventViewTransmitterBack) { - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz->state_notifications = SubGhzNotificationStateIDLE; scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneStart); return true; @@ -106,7 +97,7 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } } else if(event.type == SceneManagerEventTypeTick) { - if(subghz->state_notifications == NOTIFICATION_TX_STATE) { + if(subghz->state_notifications == SubGhzNotificationStateTX) { notification_message(subghz->notifications, &sequence_blink_red_10); } return true; @@ -117,5 +108,5 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { void subghz_scene_transmitter_on_exit(void* context) { SubGhz* subghz = context; - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz->state_notifications = SubGhzNotificationStateIDLE; } diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index 5b497e45..5ae24b7b 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -1,4 +1,5 @@ #include "subghz_i.h" +#include const char* const subghz_frequencies_text[] = { "300.00", @@ -119,6 +120,9 @@ SubGhz* subghz_alloc() { view_dispatcher_add_view( subghz->view_dispatcher, SubGhzViewWidget, widget_get_view(subghz->widget)); + //Dialog + subghz->dialogs = furi_record_open("dialogs"); + // Transmitter subghz->subghz_transmitter = subghz_transmitter_alloc(); view_dispatcher_add_view( @@ -224,6 +228,9 @@ void subghz_free(SubGhz* subghz) { view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewWidget); widget_free(subghz->widget); + //Dialog + furi_record_close("dialogs"); + // Transmitter view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewTransmitter); subghz_transmitter_free(subghz->subghz_transmitter); @@ -280,6 +287,14 @@ int32_t subghz_app(void* p) { // Check argument and run corresponding scene if(p && subghz_key_load(subghz, p)) { + string_t filename; + string_init(filename); + + path_extract_filename_no_ext(p, filename); + strlcpy( + subghz->file_name, string_get_cstr(filename), strlen(string_get_cstr(filename)) + 1); + string_clear(filename); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTransmitter); } else { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneStart); diff --git a/applications/subghz/subghz_i.c b/applications/subghz/subghz_i.c index fe8bfff1..ce693991 100644 --- a/applications/subghz/subghz_i.c +++ b/applications/subghz/subghz_i.c @@ -6,10 +6,74 @@ #include #include #include -#include "file-worker.h" +#include #include "../notification/notification.h" #include "views/subghz_receiver.h" +bool subghz_set_pteset(SubGhz* subghz, const char* preset) { + if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) { + subghz->txrx->preset = FuriHalSubGhzPresetOok270Async; + } else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) { + subghz->txrx->preset = FuriHalSubGhzPresetOok650Async; + } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) { + subghz->txrx->preset = FuriHalSubGhzPreset2FSKDev238Async; + } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) { + subghz->txrx->preset = FuriHalSubGhzPreset2FSKDev476Async; + } else { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unknown preset"); + return false; + } + return true; +} + +bool subghz_get_preset_name(SubGhz* subghz, string_t preset) { + const char* preset_name; + switch(subghz->txrx->preset) { + case FuriHalSubGhzPresetOok270Async: + preset_name = "FuriHalSubGhzPresetOok270Async"; + break; + case FuriHalSubGhzPresetOok650Async: + preset_name = "FuriHalSubGhzPresetOok650Async"; + break; + case FuriHalSubGhzPreset2FSKDev238Async: + preset_name = "FuriHalSubGhzPreset2FSKDev238Async"; + break; + case FuriHalSubGhzPreset2FSKDev476Async: + preset_name = "FuriHalSubGhzPreset2FSKDev476Async"; + break; + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unknown preset"); + default: + return false; + break; + } + string_set(preset, preset_name); + return true; +} + +void subghz_get_frequency_modulation(SubGhz* subghz, string_t frequency, string_t modulation) { + furi_assert(subghz); + if(frequency != NULL) { + string_printf( + frequency, + "%03ld.%02ld", + subghz->txrx->frequency / 1000000 % 1000, + subghz->txrx->frequency / 10000 % 100); + } + + if(modulation != NULL) { + if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async || + subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) { + string_set(modulation, "AM"); + } else if( + subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async || + subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) { + string_set(modulation, "FM"); + } else { + furi_crash(NULL); + } + } +} + void subghz_begin(SubGhz* subghz, FuriHalSubGhzPreset preset) { furi_assert(subghz); furi_hal_subghz_reset(); @@ -79,17 +143,6 @@ void subghz_sleep(SubGhz* subghz) { subghz->txrx->txrx_state = SubGhzTxRxStateSleep; } -static void subghz_frequency_preset_to_str(SubGhz* subghz, string_t output) { - furi_assert(subghz); - - string_cat_printf( - output, - "Frequency: %d\n" - "Preset: %d\n", - (int)subghz->txrx->frequency, - (int)subghz->txrx->preset); -} - bool subghz_tx_start(SubGhz* subghz) { furi_assert(subghz); @@ -144,66 +197,78 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) { furi_assert(subghz); furi_assert(file_path); - FileWorker* file_worker = file_worker_alloc(false); + Storage* storage = furi_record_open("storage"); + FlipperFile* flipper_file = flipper_file_alloc(storage); + // Load device data bool loaded = false; string_t path; string_init_set_str(path, file_path); string_t temp_str; string_init(temp_str); - int res = 0; - int data = 0; + uint32_t version; do { - if(!file_worker_open(file_worker, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { + if(!flipper_file_open_existing(flipper_file, string_get_cstr(path))) { + FURI_LOG_E( + SUBGHZ_PARSER_TAG, "Unable to open file for read: %s", string_get_cstr(path)); + break; + } + if(!flipper_file_read_header(flipper_file, temp_str, &version)) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Missing or incorrect header"); break; } - // Read and parse frequency from 1st line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { + if(((!strcmp(string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) || + (!strcmp(string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) && + version == SUBGHZ_KEY_FILE_VERSION) { + } else { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Type or version mismatch"); break; } - res = sscanf(string_get_cstr(temp_str), "Frequency: %d\n", &data); - if(res != 1) { - break; - } - subghz->txrx->frequency = (uint32_t)data; - // Read and parse preset from 2st line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { + if(!flipper_file_read_uint32( + flipper_file, "Frequency", (uint32_t*)&subghz->txrx->frequency, 1)) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Missing Frequency"); break; } - res = sscanf(string_get_cstr(temp_str), "Preset: %d\n", &data); - if(res != 1) { - break; - } - subghz->txrx->preset = (FuriHalSubGhzPreset)data; - // Read and parse name protocol from 2st line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { + if(!flipper_file_read_string(flipper_file, "Preset", temp_str)) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Missing Preset"); break; } - // strlen("Protocol: ") = 10 - string_right(temp_str, 10); + if(!subghz_set_pteset(subghz, string_get_cstr(temp_str))) { + break; + } + + if(!flipper_file_read_string(flipper_file, "Protocol", temp_str)) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Missing Protocol"); + break; + } + subghz->txrx->protocol_result = subghz_parser_get_by_name(subghz->txrx->parser, string_get_cstr(temp_str)); if(subghz->txrx->protocol_result == NULL) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "This type of protocol was not found"); break; } if(!subghz->txrx->protocol_result->to_load_protocol_from_file( - file_worker, subghz->txrx->protocol_result, string_get_cstr(path))) { + flipper_file, subghz->txrx->protocol_result, string_get_cstr(path))) { break; } loaded = true; } while(0); if(!loaded) { - file_worker_show_error(file_worker, "Cannot parse\nfile"); + dialog_message_show_storage_error(subghz->dialogs, "Cannot parse\nfile"); } string_clear(temp_str); string_clear(path); - file_worker_close(file_worker); - file_worker_free(file_worker); + + flipper_file_close(flipper_file); + flipper_file_free(flipper_file); + + furi_record_close("storage"); return loaded; } @@ -211,23 +276,22 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) { bool subghz_get_next_name_file(SubGhz* subghz) { furi_assert(subghz); - FileWorker* file_worker = file_worker_alloc(false); + Storage* storage = furi_record_open("storage"); string_t temp_str; string_init(temp_str); bool res = false; if(strcmp(subghz->file_name, "")) { //get the name of the next free file - file_worker_get_next_filename( - file_worker, SUBGHZ_RAW_PATH_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION, temp_str); + storage_get_next_filename( + storage, SUBGHZ_RAW_PATH_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION, temp_str); memcpy(subghz->file_name, string_get_cstr(temp_str), strlen(string_get_cstr(temp_str))); res = true; } string_clear(temp_str); - file_worker_close(file_worker); - file_worker_free(file_worker); + furi_record_close("storage"); return res; } @@ -236,7 +300,8 @@ bool subghz_save_protocol_to_file(SubGhz* subghz, const char* dev_name) { furi_assert(subghz); furi_assert(subghz->txrx->protocol_result); - FileWorker* file_worker = file_worker_alloc(false); + Storage* storage = furi_record_open("storage"); + FlipperFile* flipper_file = flipper_file_alloc(storage); string_t dev_file_name; string_init(dev_file_name); string_t temp_str; @@ -244,43 +309,71 @@ bool subghz_save_protocol_to_file(SubGhz* subghz, const char* dev_name) { bool saved = false; do { + // Checking that this type of people can be saved + if(subghz->txrx->protocol_result->to_save_file == NULL) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "No saving of this type of keys"); + break; + } // Create subghz folder directory if necessary - if(!file_worker_mkdir(file_worker, SUBGHZ_APP_FOLDER)) { + if(!storage_simply_mkdir(storage, SUBGHZ_APP_FOLDER)) { + dialog_message_show_storage_error(subghz->dialogs, "Cannot create\nfolder"); break; } // Create saved directory if necessary - if(!file_worker_mkdir(file_worker, SUBGHZ_APP_PATH_FOLDER)) { + if(!storage_simply_mkdir(storage, SUBGHZ_APP_FOLDER)) { + dialog_message_show_storage_error(subghz->dialogs, "Cannot create\nfolder"); break; } + // First remove subghz device file if it was saved string_printf( dev_file_name, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, dev_name, SUBGHZ_APP_EXTENSION); - if(!file_worker_remove(file_worker, string_get_cstr(dev_file_name))) { + + if(!storage_simply_remove(storage, string_get_cstr(dev_file_name))) { break; } + // Open file - if(!file_worker_open( - file_worker, string_get_cstr(dev_file_name), FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + if(!flipper_file_open_always(flipper_file, string_get_cstr(dev_file_name))) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unable to open file for write: %s", dev_file_name); break; } - //Get string frequency preset protocol - subghz_frequency_preset_to_str(subghz, temp_str); - if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_size(temp_str))) { + + if(!flipper_file_write_header_cstr( + flipper_file, SUBGHZ_KEY_FILE_TYPE, SUBGHZ_KEY_FILE_VERSION)) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unable to add header"); break; } - //Get string save - subghz->txrx->protocol_result->to_save_string(subghz->txrx->protocol_result, temp_str); - // Prepare and write data to file - if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_size(temp_str))) { + + if(!flipper_file_write_uint32( + flipper_file, "Frequency", (uint32_t*)&subghz->txrx->frequency, 1)) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unable to add Frequency"); break; } + + if(!subghz_get_preset_name(subghz, temp_str)) { + break; + } + if(!flipper_file_write_string_cstr(flipper_file, "Preset", string_get_cstr(temp_str))) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unable to add Preset"); + break; + } + + if(!subghz->txrx->protocol_result->to_save_file( + subghz->txrx->protocol_result, flipper_file)) { + break; + } + saved = true; } while(0); string_clear(temp_str); string_clear(dev_file_name); - file_worker_close(file_worker); - file_worker_free(file_worker); + + flipper_file_close(flipper_file); + flipper_file_free(flipper_file); + + furi_record_close("storage"); return saved; } @@ -288,17 +381,12 @@ bool subghz_save_protocol_to_file(SubGhz* subghz, const char* dev_name) { bool subghz_load_protocol_from_file(SubGhz* subghz) { furi_assert(subghz); - FileWorker* file_worker = file_worker_alloc(false); - string_t protocol_file_name; - string_init(protocol_file_name); - string_t temp_str; - string_init(temp_str); - int sscanf_res = 0; - int data = 0; + string_t file_name; + string_init(file_name); // Input events and views are managed by file_select - bool res = file_worker_file_select( - file_worker, + bool res = dialog_file_select_show( + subghz->dialogs, SUBGHZ_APP_PATH_FOLDER, SUBGHZ_APP_EXTENSION, subghz->file_name, @@ -306,87 +394,24 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { NULL); if(res) { - // Get key file path string_printf( - protocol_file_name, - "%s/%s%s", - SUBGHZ_APP_PATH_FOLDER, - subghz->file_name, - SUBGHZ_APP_EXTENSION); - } else { - string_clear(temp_str); - string_clear(protocol_file_name); + file_name, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION); - file_worker_close(file_worker); - file_worker_free(file_worker); - return res; - } - res = false; - do { - if(!file_worker_open( - file_worker, string_get_cstr(protocol_file_name), FSAM_READ, FSOM_OPEN_EXISTING)) { - return res; - } - // Read and parse frequency from 1st line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - sscanf_res = sscanf(string_get_cstr(temp_str), "Frequency: %d\n", &data); - if(sscanf_res != 1) { - break; - } - subghz->txrx->frequency = (uint32_t)data; - - // Read and parse preset from 2st line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - sscanf_res = sscanf(string_get_cstr(temp_str), "Preset: %d\n", &data); - if(sscanf_res != 1) { - break; - } - subghz->txrx->preset = (FuriHalSubGhzPreset)data; - - // Read and parse name protocol from 3st line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - // strlen("Protocol: ") = 10 - string_right(temp_str, 10); - subghz->txrx->protocol_result = - subghz_parser_get_by_name(subghz->txrx->parser, string_get_cstr(temp_str)); - if(subghz->txrx->protocol_result == NULL) { - break; - } - - if(subghz->txrx->protocol_result->to_load_protocol_from_file == NULL || - !subghz->txrx->protocol_result->to_load_protocol_from_file( - file_worker, subghz->txrx->protocol_result, string_get_cstr(protocol_file_name))) { - break; - } - res = true; - } while(0); - - if(!res) { - file_worker_show_error(file_worker, "Cannot parse\nfile"); + res = subghz_key_load(subghz, string_get_cstr(file_name)); } - string_clear(temp_str); - string_clear(protocol_file_name); - - file_worker_close(file_worker); - file_worker_free(file_worker); + string_clear(file_name); return res; } bool subghz_rename_file(SubGhz* subghz) { furi_assert(subghz); - bool ret = false; + bool ret = true; string_t old_path; string_t new_path; - FileWorker* file_worker = file_worker_alloc(false); + Storage* storage = furi_record_open("storage"); string_init_printf( old_path, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name_tmp, SUBGHZ_APP_EXTENSION); @@ -394,39 +419,33 @@ bool subghz_rename_file(SubGhz* subghz) { string_init_printf( new_path, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION); - ret = file_worker_rename(file_worker, string_get_cstr(old_path), string_get_cstr(new_path)); + FS_Error fs_result = + storage_common_rename(storage, string_get_cstr(old_path), string_get_cstr(new_path)); + + if(fs_result != FSE_OK && fs_result != FSE_EXIST) { + dialog_message_show_storage_error(subghz->dialogs, "Cannot rename\n file/directory"); + ret = false; + } + string_clear(old_path); string_clear(new_path); - file_worker_close(file_worker); - file_worker_free(file_worker); + furi_record_close("storage"); + return ret; } bool subghz_delete_file(SubGhz* subghz) { furi_assert(subghz); - bool result = true; - FileWorker* file_worker = file_worker_alloc(false); + Storage* storage = furi_record_open("storage"); string_t file_path; + string_init_printf( + file_path, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name_tmp, SUBGHZ_APP_EXTENSION); + bool result = storage_simply_remove(storage, string_get_cstr(file_path)); + furi_record_close("storage"); - do { - // Get key file path - string_init_printf( - file_path, - "%s/%s%s", - SUBGHZ_APP_PATH_FOLDER, - subghz->file_name_tmp, - SUBGHZ_APP_EXTENSION); - // Delete original file - if(!file_worker_remove(file_worker, string_get_cstr(file_path))) { - result = false; - break; - } - } while(0); + subghz_file_name_clear(subghz); - string_clear(file_path); - file_worker_close(file_worker); - file_worker_free(file_worker); return result; } diff --git a/applications/subghz/subghz_i.h b/applications/subghz/subghz_i.h index 70a39f23..ef27721d 100644 --- a/applications/subghz/subghz_i.h +++ b/applications/subghz/subghz_i.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -33,11 +34,6 @@ #define SUBGHZ_TEXT_STORE_SIZE 40 -#define NOTIFICATION_STARTING_STATE 0u -#define NOTIFICATION_IDLE_STATE 1u -#define NOTIFICATION_TX_STATE 2u -#define NOTIFICATION_RX_STATE 3u - extern const char* const subghz_frequencies_text[]; extern const uint32_t subghz_frequencies[]; extern const uint32_t subghz_hopper_frequencies[]; @@ -45,6 +41,14 @@ extern const uint32_t subghz_frequencies_count; extern const uint32_t subghz_hopper_frequencies_count; extern const uint32_t subghz_frequencies_433_92; +/** SubGhzNotification state */ +typedef enum { + SubGhzNotificationStateStarting, + SubGhzNotificationStateIDLE, + SubGhzNotificationStateTX, + SubGhzNotificationStateRX, +} SubGhzNotificationState; + /** SubGhzTxRx state */ typedef enum { SubGhzTxRxStateIDLE, @@ -101,9 +105,10 @@ struct SubGhz { Popup* popup; TextInput* text_input; Widget* widget; + DialogsApp* dialogs; char file_name[SUBGHZ_TEXT_STORE_SIZE + 1]; char file_name_tmp[SUBGHZ_TEXT_STORE_SIZE + 1]; - uint8_t state_notifications; + SubGhzNotificationState state_notifications; SubghzReceiver* subghz_receiver; SubghzTransmitter* subghz_transmitter; @@ -133,6 +138,9 @@ typedef enum { SubGhzViewTestPacket, } SubGhzView; +bool subghz_set_pteset(SubGhz* subghz, const char* preset); +bool subghz_get_preset_name(SubGhz* subghz, string_t preset); +void subghz_get_frequency_modulation(SubGhz* subghz, string_t frequency, string_t modulation); void subghz_begin(SubGhz* subghz, FuriHalSubGhzPreset preset); uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency); void subghz_rx_end(SubGhz* subghz); diff --git a/applications/subghz/views/subghz_test_static.c b/applications/subghz/views/subghz_test_static.c index aa701464..bc672406 100644 --- a/applications/subghz/views/subghz_test_static.c +++ b/applications/subghz/views/subghz_test_static.c @@ -8,6 +8,8 @@ #include #include +#define TAG "SubGhzTestStatic" + typedef enum { SubghzTestStaticStatusIDLE, SubghzTestStaticStatusTX, @@ -99,7 +101,7 @@ bool subghz_test_static_input(InputEvent* event, void* context) { } else { notification_message_block(notification, &sequence_set_red_255); - FURI_LOG_I("SubghzTestStatic", "TX Start"); + FURI_LOG_I(TAG, "TX Start"); subghz_encoder_princeton_set( instance->encoder, subghz_test_static_keys[model->button], 10000); @@ -110,7 +112,7 @@ bool subghz_test_static_input(InputEvent* event, void* context) { } } else if(event->type == InputTypeRelease) { if(instance->satus_tx == SubghzTestStaticStatusTX) { - FURI_LOG_I("SubghzTestStatic", "TX Stop"); + FURI_LOG_I(TAG, "TX Stop"); subghz_encoder_princeton_print_log(instance->encoder); furi_hal_subghz_stop_async_tx(); notification_message(notification, &sequence_reset_red); diff --git a/applications/tests/rpc/rpc_test.c b/applications/tests/rpc/rpc_test.c index 51ed30cf..af99be4a 100644 --- a/applications/tests/rpc/rpc_test.c +++ b/applications/tests/rpc/rpc_test.c @@ -29,7 +29,7 @@ static RpcSession* session = NULL; static StreamBufferHandle_t output_stream = NULL; static uint32_t command_id = 0; -#define TEST_RPC_TAG "TEST_RPC" +#define TAG "UnitTestsRpc" #define MAX_RECEIVE_OUTPUT_TIMEOUT 3000 #define MAX_NAME_LENGTH 255 #define MAX_DATA_SIZE 512 // have to be exact as in rpc_storage.c @@ -1334,7 +1334,7 @@ int run_minunit_test_rpc() { Storage* storage = furi_record_open("storage"); furi_record_close("storage"); if(storage_sd_status(storage) != FSE_OK) { - FURI_LOG_E("UNIT_TESTS", "SD card not mounted - skip storage tests"); + FURI_LOG_E(TAG, "SD card not mounted - skip storage tests"); } else { MU_RUN_SUITE(test_rpc_storage); } diff --git a/applications/tests/test_index.c b/applications/tests/test_index.c index f436c0ef..f5607566 100644 --- a/applications/tests/test_index.c +++ b/applications/tests/test_index.c @@ -8,7 +8,7 @@ #include #include -#define TESTS_TAG "UNIT_TESTS" +#define TAG "UnitTests" int run_minunit(); int run_minunit_test_irda_decoder_encoder(); @@ -42,7 +42,7 @@ void unit_tests_cli(Cli* cli, string_t args, void* context) { // TODO: lock device while test running if(loader_is_locked(loader)) { - FURI_LOG_E(TESTS_TAG, "RPC: stop all applications to run tests"); + FURI_LOG_E(TAG, "RPC: stop all applications to run tests"); notification_message(notification, &sequence_blink_magenta_100); } else { notification_message_block(notification, &sequence_set_only_blue_255); @@ -56,21 +56,21 @@ void unit_tests_cli(Cli* cli, string_t args, void* context) { test_result |= run_minunit_test_flipper_file(); cycle_counter = (DWT->CYCCNT - cycle_counter); - FURI_LOG_I(TESTS_TAG, "Consumed: %0.2fs", (float)cycle_counter / (SystemCoreClock)); + FURI_LOG_I(TAG, "Consumed: %0.2fs", (float)cycle_counter / (SystemCoreClock)); if(test_result == 0) { delay(200); /* wait for tested services and apps to deallocate */ uint32_t heap_after = memmgr_get_free_heap(); notification_message(notification, &sequence_success); if(heap_after != heap_before) { - FURI_LOG_E(TESTS_TAG, "Leaked: %d", heap_before - heap_after); + FURI_LOG_E(TAG, "Leaked: %d", heap_before - heap_after); } else { - FURI_LOG_I(TESTS_TAG, "No leaks"); + FURI_LOG_I(TAG, "No leaks"); } - FURI_LOG_I(TESTS_TAG, "PASSED"); + FURI_LOG_I(TAG, "PASSED"); } else { notification_message(notification, &sequence_error); - FURI_LOG_E(TESTS_TAG, "FAILED"); + FURI_LOG_E(TAG, "FAILED"); } } diff --git a/assets/compiled/flipper.pb.h b/assets/compiled/flipper.pb.h index 161b969d..49b5fdee 100644 --- a/assets/compiled/flipper.pb.h +++ b/assets/compiled/flipper.pb.h @@ -36,7 +36,10 @@ typedef enum _PB_CommandStatus { PB_CommandStatus_ERROR_STORAGE_DIR_NOT_EMPTY = 18, /* *< Directory, you're going to remove is not empty */ /* *< Application Errors */ PB_CommandStatus_ERROR_APP_CANT_START = 16, /* *< Can't start app - internal error */ - PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED = 17 /* *< Another app is running */ + PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED = 17, /* *< Another app is running */ + /* *< Virtual Display Errors */ + PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_ALREADY_STARTED = 19, /* *< Virtual Display session can't be started twice */ + PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_NOT_STARTED = 20 /* *< Virtual Display session can't be stopped when it's not started */ } PB_CommandStatus; /* Struct definitions */ @@ -76,18 +79,20 @@ typedef struct _PB_Main { PB_StopSession stop_session; PB_Gui_StartScreenStreamRequest gui_start_screen_stream_request; PB_Gui_StopScreenStreamRequest gui_stop_screen_stream_request; - PB_Gui_ScreenStreamFrame gui_screen_stream_frame; + PB_Gui_ScreenFrame gui_screen_frame; PB_Gui_SendInputEventRequest gui_send_input_event_request; PB_Storage_StatRequest storage_stat_request; PB_Storage_StatResponse storage_stat_response; + PB_Gui_StartVirtualDisplayRequest gui_start_virtual_display_request; + PB_Gui_StopVirtualDisplayRequest gui_stop_virtual_display_request; } content; } PB_Main; /* Helper constants for enums */ #define _PB_CommandStatus_MIN PB_CommandStatus_OK -#define _PB_CommandStatus_MAX PB_CommandStatus_ERROR_STORAGE_DIR_NOT_EMPTY -#define _PB_CommandStatus_ARRAYSIZE ((PB_CommandStatus)(PB_CommandStatus_ERROR_STORAGE_DIR_NOT_EMPTY+1)) +#define _PB_CommandStatus_MAX PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_NOT_STARTED +#define _PB_CommandStatus_ARRAYSIZE ((PB_CommandStatus)(PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_NOT_STARTED+1)) #ifdef __cplusplus @@ -124,10 +129,12 @@ extern "C" { #define PB_Main_stop_session_tag 19 #define PB_Main_gui_start_screen_stream_request_tag 20 #define PB_Main_gui_stop_screen_stream_request_tag 21 -#define PB_Main_gui_screen_stream_frame_tag 22 +#define PB_Main_gui_screen_frame_tag 22 #define PB_Main_gui_send_input_event_request_tag 23 #define PB_Main_storage_stat_request_tag 24 #define PB_Main_storage_stat_response_tag 25 +#define PB_Main_gui_start_virtual_display_request_tag 26 +#define PB_Main_gui_stop_virtual_display_request_tag 27 /* Struct field encoding specification for nanopb */ #define PB_Empty_FIELDLIST(X, a) \ @@ -162,10 +169,12 @@ X(a, STATIC, ONEOF, MSG_W_CB, (content,app_lock_status_response,content.app X(a, STATIC, ONEOF, MSG_W_CB, (content,stop_session,content.stop_session), 19) \ X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_start_screen_stream_request,content.gui_start_screen_stream_request), 20) \ X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_stop_screen_stream_request,content.gui_stop_screen_stream_request), 21) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_screen_stream_frame,content.gui_screen_stream_frame), 22) \ +X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_screen_frame,content.gui_screen_frame), 22) \ X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_send_input_event_request,content.gui_send_input_event_request), 23) \ X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_stat_request,content.storage_stat_request), 24) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_stat_response,content.storage_stat_response), 25) +X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_stat_response,content.storage_stat_response), 25) \ +X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_start_virtual_display_request,content.gui_start_virtual_display_request), 26) \ +X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_stop_virtual_display_request,content.gui_stop_virtual_display_request), 27) #define PB_Main_CALLBACK NULL #define PB_Main_DEFAULT NULL #define PB_Main_content_empty_MSGTYPE PB_Empty @@ -186,10 +195,12 @@ X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_stat_response,content.storag #define PB_Main_content_stop_session_MSGTYPE PB_StopSession #define PB_Main_content_gui_start_screen_stream_request_MSGTYPE PB_Gui_StartScreenStreamRequest #define PB_Main_content_gui_stop_screen_stream_request_MSGTYPE PB_Gui_StopScreenStreamRequest -#define PB_Main_content_gui_screen_stream_frame_MSGTYPE PB_Gui_ScreenStreamFrame +#define PB_Main_content_gui_screen_frame_MSGTYPE PB_Gui_ScreenFrame #define PB_Main_content_gui_send_input_event_request_MSGTYPE PB_Gui_SendInputEventRequest #define PB_Main_content_storage_stat_request_MSGTYPE PB_Storage_StatRequest #define PB_Main_content_storage_stat_response_MSGTYPE PB_Storage_StatResponse +#define PB_Main_content_gui_start_virtual_display_request_MSGTYPE PB_Gui_StartVirtualDisplayRequest +#define PB_Main_content_gui_stop_virtual_display_request_MSGTYPE PB_Gui_StopVirtualDisplayRequest extern const pb_msgdesc_t PB_Empty_msg; extern const pb_msgdesc_t PB_StopSession_msg; @@ -203,9 +214,9 @@ extern const pb_msgdesc_t PB_Main_msg; /* Maximum encoded size of messages (where known) */ #define PB_Empty_size 0 #define PB_StopSession_size 0 -#if defined(PB_Storage_ListRequest_size) && defined(PB_Storage_ListResponse_size) && defined(PB_Storage_ReadRequest_size) && defined(PB_Storage_ReadResponse_size) && defined(PB_Storage_WriteRequest_size) && defined(PB_Storage_DeleteRequest_size) && defined(PB_Storage_MkdirRequest_size) && defined(PB_Storage_Md5sumRequest_size) && defined(PB_App_StartRequest_size) && defined(PB_Gui_ScreenStreamFrame_size) && defined(PB_Storage_StatRequest_size) && defined(PB_Storage_StatResponse_size) +#if defined(PB_Storage_ListRequest_size) && defined(PB_Storage_ListResponse_size) && defined(PB_Storage_ReadRequest_size) && defined(PB_Storage_ReadResponse_size) && defined(PB_Storage_WriteRequest_size) && defined(PB_Storage_DeleteRequest_size) && defined(PB_Storage_MkdirRequest_size) && defined(PB_Storage_Md5sumRequest_size) && defined(PB_App_StartRequest_size) && defined(PB_Gui_ScreenFrame_size) && defined(PB_Storage_StatRequest_size) && defined(PB_Storage_StatResponse_size) #define PB_Main_size (10 + sizeof(union PB_Main_content_size_union)) -union PB_Main_content_size_union {char f7[(6 + PB_Storage_ListRequest_size)]; char f8[(6 + PB_Storage_ListResponse_size)]; char f9[(6 + PB_Storage_ReadRequest_size)]; char f10[(6 + PB_Storage_ReadResponse_size)]; char f11[(6 + PB_Storage_WriteRequest_size)]; char f12[(6 + PB_Storage_DeleteRequest_size)]; char f13[(6 + PB_Storage_MkdirRequest_size)]; char f14[(6 + PB_Storage_Md5sumRequest_size)]; char f16[(7 + PB_App_StartRequest_size)]; char f22[(7 + PB_Gui_ScreenStreamFrame_size)]; char f24[(7 + PB_Storage_StatRequest_size)]; char f25[(7 + PB_Storage_StatResponse_size)]; char f0[36];}; +union PB_Main_content_size_union {char f7[(6 + PB_Storage_ListRequest_size)]; char f8[(6 + PB_Storage_ListResponse_size)]; char f9[(6 + PB_Storage_ReadRequest_size)]; char f10[(6 + PB_Storage_ReadResponse_size)]; char f11[(6 + PB_Storage_WriteRequest_size)]; char f12[(6 + PB_Storage_DeleteRequest_size)]; char f13[(6 + PB_Storage_MkdirRequest_size)]; char f14[(6 + PB_Storage_Md5sumRequest_size)]; char f16[(7 + PB_App_StartRequest_size)]; char f22[(7 + PB_Gui_ScreenFrame_size)]; char f24[(7 + PB_Storage_StatRequest_size)]; char f25[(7 + PB_Storage_StatResponse_size)]; char f0[36];}; #endif #ifdef __cplusplus diff --git a/assets/compiled/gui.pb.c b/assets/compiled/gui.pb.c index ecc8a647..2c1d8490 100644 --- a/assets/compiled/gui.pb.c +++ b/assets/compiled/gui.pb.c @@ -6,18 +6,24 @@ #error Regenerate this file with the current version of nanopb generator. #endif +PB_BIND(PB_Gui_ScreenFrame, PB_Gui_ScreenFrame, AUTO) + + PB_BIND(PB_Gui_StartScreenStreamRequest, PB_Gui_StartScreenStreamRequest, AUTO) PB_BIND(PB_Gui_StopScreenStreamRequest, PB_Gui_StopScreenStreamRequest, AUTO) -PB_BIND(PB_Gui_ScreenStreamFrame, PB_Gui_ScreenStreamFrame, AUTO) - - PB_BIND(PB_Gui_SendInputEventRequest, PB_Gui_SendInputEventRequest, AUTO) +PB_BIND(PB_Gui_StartVirtualDisplayRequest, PB_Gui_StartVirtualDisplayRequest, AUTO) + + +PB_BIND(PB_Gui_StopVirtualDisplayRequest, PB_Gui_StopVirtualDisplayRequest, AUTO) + + diff --git a/assets/compiled/gui.pb.h b/assets/compiled/gui.pb.h index abb702fb..84cf1d57 100644 --- a/assets/compiled/gui.pb.h +++ b/assets/compiled/gui.pb.h @@ -28,18 +28,26 @@ typedef enum _PB_Gui_InputType { } PB_Gui_InputType; /* Struct definitions */ -typedef struct _PB_Gui_ScreenStreamFrame { +typedef struct _PB_Gui_ScreenFrame { pb_bytes_array_t *data; -} PB_Gui_ScreenStreamFrame; +} PB_Gui_ScreenFrame; typedef struct _PB_Gui_StartScreenStreamRequest { char dummy_field; } PB_Gui_StartScreenStreamRequest; +typedef struct _PB_Gui_StartVirtualDisplayRequest { + char dummy_field; +} PB_Gui_StartVirtualDisplayRequest; + typedef struct _PB_Gui_StopScreenStreamRequest { char dummy_field; } PB_Gui_StopScreenStreamRequest; +typedef struct _PB_Gui_StopVirtualDisplayRequest { + char dummy_field; +} PB_Gui_StopVirtualDisplayRequest; + typedef struct _PB_Gui_SendInputEventRequest { PB_Gui_InputKey key; PB_Gui_InputType type; @@ -61,21 +69,30 @@ extern "C" { #endif /* Initializer values for message structs */ +#define PB_Gui_ScreenFrame_init_default {NULL} #define PB_Gui_StartScreenStreamRequest_init_default {0} #define PB_Gui_StopScreenStreamRequest_init_default {0} -#define PB_Gui_ScreenStreamFrame_init_default {NULL} #define PB_Gui_SendInputEventRequest_init_default {_PB_Gui_InputKey_MIN, _PB_Gui_InputType_MIN} +#define PB_Gui_StartVirtualDisplayRequest_init_default {0} +#define PB_Gui_StopVirtualDisplayRequest_init_default {0} +#define PB_Gui_ScreenFrame_init_zero {NULL} #define PB_Gui_StartScreenStreamRequest_init_zero {0} #define PB_Gui_StopScreenStreamRequest_init_zero {0} -#define PB_Gui_ScreenStreamFrame_init_zero {NULL} #define PB_Gui_SendInputEventRequest_init_zero {_PB_Gui_InputKey_MIN, _PB_Gui_InputType_MIN} +#define PB_Gui_StartVirtualDisplayRequest_init_zero {0} +#define PB_Gui_StopVirtualDisplayRequest_init_zero {0} /* Field tags (for use in manual encoding/decoding) */ -#define PB_Gui_ScreenStreamFrame_data_tag 1 +#define PB_Gui_ScreenFrame_data_tag 1 #define PB_Gui_SendInputEventRequest_key_tag 1 #define PB_Gui_SendInputEventRequest_type_tag 2 /* Struct field encoding specification for nanopb */ +#define PB_Gui_ScreenFrame_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, BYTES, data, 1) +#define PB_Gui_ScreenFrame_CALLBACK NULL +#define PB_Gui_ScreenFrame_DEFAULT NULL + #define PB_Gui_StartScreenStreamRequest_FIELDLIST(X, a) \ #define PB_Gui_StartScreenStreamRequest_CALLBACK NULL @@ -86,33 +103,44 @@ extern "C" { #define PB_Gui_StopScreenStreamRequest_CALLBACK NULL #define PB_Gui_StopScreenStreamRequest_DEFAULT NULL -#define PB_Gui_ScreenStreamFrame_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, BYTES, data, 1) -#define PB_Gui_ScreenStreamFrame_CALLBACK NULL -#define PB_Gui_ScreenStreamFrame_DEFAULT NULL - #define PB_Gui_SendInputEventRequest_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, key, 1) \ X(a, STATIC, SINGULAR, UENUM, type, 2) #define PB_Gui_SendInputEventRequest_CALLBACK NULL #define PB_Gui_SendInputEventRequest_DEFAULT NULL +#define PB_Gui_StartVirtualDisplayRequest_FIELDLIST(X, a) \ + +#define PB_Gui_StartVirtualDisplayRequest_CALLBACK NULL +#define PB_Gui_StartVirtualDisplayRequest_DEFAULT NULL + +#define PB_Gui_StopVirtualDisplayRequest_FIELDLIST(X, a) \ + +#define PB_Gui_StopVirtualDisplayRequest_CALLBACK NULL +#define PB_Gui_StopVirtualDisplayRequest_DEFAULT NULL + +extern const pb_msgdesc_t PB_Gui_ScreenFrame_msg; extern const pb_msgdesc_t PB_Gui_StartScreenStreamRequest_msg; extern const pb_msgdesc_t PB_Gui_StopScreenStreamRequest_msg; -extern const pb_msgdesc_t PB_Gui_ScreenStreamFrame_msg; extern const pb_msgdesc_t PB_Gui_SendInputEventRequest_msg; +extern const pb_msgdesc_t PB_Gui_StartVirtualDisplayRequest_msg; +extern const pb_msgdesc_t PB_Gui_StopVirtualDisplayRequest_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define PB_Gui_ScreenFrame_fields &PB_Gui_ScreenFrame_msg #define PB_Gui_StartScreenStreamRequest_fields &PB_Gui_StartScreenStreamRequest_msg #define PB_Gui_StopScreenStreamRequest_fields &PB_Gui_StopScreenStreamRequest_msg -#define PB_Gui_ScreenStreamFrame_fields &PB_Gui_ScreenStreamFrame_msg #define PB_Gui_SendInputEventRequest_fields &PB_Gui_SendInputEventRequest_msg +#define PB_Gui_StartVirtualDisplayRequest_fields &PB_Gui_StartVirtualDisplayRequest_msg +#define PB_Gui_StopVirtualDisplayRequest_fields &PB_Gui_StopVirtualDisplayRequest_msg /* Maximum encoded size of messages (where known) */ -/* PB_Gui_ScreenStreamFrame_size depends on runtime parameters */ +/* PB_Gui_ScreenFrame_size depends on runtime parameters */ #define PB_Gui_SendInputEventRequest_size 4 #define PB_Gui_StartScreenStreamRequest_size 0 +#define PB_Gui_StartVirtualDisplayRequest_size 0 #define PB_Gui_StopScreenStreamRequest_size 0 +#define PB_Gui_StopVirtualDisplayRequest_size 0 #ifdef __cplusplus } /* extern "C" */ diff --git a/assets/protobuf b/assets/protobuf index 0e6d374a..6be7def6 160000 --- a/assets/protobuf +++ b/assets/protobuf @@ -1 +1 @@ -Subproject commit 0e6d374ab1a12f95a3cd04444376a261e7252db4 +Subproject commit 6be7def6087c4d277386381ff2792fa622933668 diff --git a/assets/resources/nfc/emv/aid.nfc b/assets/resources/nfc/emv/aid.nfc index 2655df56..43854f3d 100644 --- a/assets/resources/nfc/emv/aid.nfc +++ b/assets/resources/nfc/emv/aid.nfc @@ -1,148 +1,151 @@ -A00000000305076010 VISA ELO Credit -A0000000031010 VISA Debit/Credit (Classic) -A000000003101001 VISA Credit -A000000003101002 VISA Debit -A0000000032010 VISA Electron -A0000000032020 VISA -A0000000033010 VISA Interlink -A0000000034010 VISA Specific -A0000000035010 VISA Specific -A0000000036010 Domestic Visa Cash -A0000000036020 International Visa Cash -A0000000038002 VISA Auth EMV-CAP (DPA) -A0000000038010 VISA Plus -A0000000039010 VISA Loyalty -A000000003999910 VISA Proprietary ATM -A00000000401 MasterCard PayPass -A0000000041010 MasterCard Global -A00000000410101213 MasterCard Credit -A00000000410101215 MasterCard Credit -A0000000042010 MasterCard Specific -A0000000043010 MasterCard Specific -A0000000043060 Maestro (Debit) -A000000004306001 Maestro (Debit) -A0000000044010 MasterCard Specific -A0000000045010 MasterCard Specific -A0000000046000 Cirrus -A0000000048002 SecureCode EMV-CAP -A0000000049999 MasterCard PayPass -A0000000050001 Maestro UK -A0000000050002 Solo -A00000002401 Self Service -A000000025 American Express -A0000000250000 American Express -A00000002501 American Express -A000000025010402 American Express -A000000025010701 ExpressPay -A000000025010801 American Express -A0000000291010 Link / American Express -A0000000421010 Cartes Bancaire EMV Card -A0000000426010 Apple Pay -A00000006510 JCB -A0000000651010 JCB J Smart Credit -A00000006900 Moneo -A000000077010000021000000000003B Visa AEPN -A000000098 Debit Card -A0000000980848 Debit Card -A0000001211010 Dankort VISA GEM Vision -A0000001410001 PagoBANCOMAT -A0000001523010 Discover, Pulse D Pas -A0000001524010 Discover -A0000001544442 Banricompras Debito -A000000172950001 BAROC Taiwan -A0000002281010 SPAN (M/Chip) -A0000002282010 SPAN (VIS) -A0000002771010 INTERAC -A00000031510100528 Currence PuC -A0000003156020 Chipknip -A0000003591010028001 Girocard EAPS -A0000003710001 InterSwitch Verve Card -A0000004540010 Etranzact Genesis Card -A0000004540011 Etranzact Genesis Card 2 -A0000004766C GOOGLE_PAYMENT -A0000005241010 RuPay -A0000006723010 TROY chip credit card -A0000006723020 TROY chip debit card -A0000007705850 XTRAPOWER -B012345678 Maestro TEST -D27600002545500100 Girocard -D5780000021010 Bankaxept -F0000000030001 BRADESCO -A000000003000000 (VISA) Card Manager -A000000003534441 Schlumberger SD -A0000000035350 Security Domain -A000000003535041 Security Domain -A0000000040000 MasterCard Card Manager -A000000018434D Gemplus card manager -A000000018434D00 Gemplus Security Domain -A0000000960200 Proton WISD -A0000001510000 Global Platform SD -A00000015153504341534400 CASD_AID -A000000476A010 GSD_MANAGER_AID -A000000476A110 GSD_MANAGER_AID -315041592E5359532E4444463031 Visa PSE -325041592E5359532E4444463031 Visa PPSE -A0000000042203 MasterCard Specific -A0000000045555 APDULogger -A0000000090001FF44FF1289 Orange -A0000000101030 Maestro-CH -A00000001800 Gemplus -A0000000181001 gemplus util packages -A000000025010104 American Express -A00000002949034010100001 HSBC -A00000002949282010100000 Barclay -A00000005945430100 Girocard Electronic Cash -A0000000980840 Visa Common Debit -A0000001570010 AMEX -A0000001570020 MasterCard -A0000001570021 Maestro -A0000001570022 Maestro -A0000001570023 CASH -A0000001570030 VISA -A0000001570031 VISA -A0000001570040 JCB -A0000001570050 Postcard -A0000001570051 Postcard -A0000001570100 MCard -A0000001570104 MyOne -A000000157010C WIRCard -A000000157010D Power Card -A0000001574443 DINERS CLUB -A0000001574444 Supercard Plus -A00000022820101010 SPAN -A000000308000010000100 ID-ONE PIV BIO -A0000003241010 Discover Zip -A000000333010101 UnionPay Debit -A000000333010102 UnionPay Credit -A000000333010103 UnionPay Quasi Credit -A000000333010106 UnionPay Electronic Cash -A000000333010108 U.S. UnionPay Common Debit -A000000337102000 Classic -A000000337101001 Prepaye Online -A000000337102001 Prepaye Possibile Offiline -A000000337601001 Porte Monnaie Electronique -A0000006581010 MIR Credit -A0000006581011 MIR Credit -A0000006582010 MIR Debit -D040000001000002 Paylife Quick IEP -D040000002000002 RFU -D040000003000002 POS -D040000004000002 ATM -D04000000B000002 Retail -D04000000C000002 Bank_Data -D04000000D000002 Shopping -D040000013000001 DF_UNI_Kepler1 -D040000013000001 DF_Schüler1 -D040000013000002 DF_UNI_Kepler2 -D040000013000002 DF_Schüler2 -D040000014000001 DF_Mensa -D040000015000001 DF_UNI_Ausweis -D040000015000001 DF_Ausweis -D0400000190001 EMV ATM Maestro -D0400000190002 EMV POS Maestro -D0400000190003 EMV ATM MasterCard -D0400000190004 EMV POS MasterCard -D276000025 Girocard -D27600002547410100 Girocard ATM -D7560000010101 Reka Card -D7560000300101 M Budget \ No newline at end of file +Filetype: Flipper EMV resources +Version: 1 +# EMV Application ID code: Application ID name +A00000000305076010: VISA ELO Credit +A0000000031010: VISA Debit/Credit (Classic) +A000000003101001: VISA Credit +A000000003101002: VISA Debit +A0000000032010: VISA Electron +A0000000032020: VISA +A0000000033010: VISA Interlink +A0000000034010: VISA Specific +A0000000035010: VISA Specific +A0000000036010: Domestic Visa Cash +A0000000036020: International Visa Cash +A0000000038002: VISA Auth EMV-CAP (DPA) +A0000000038010: VISA Plus +A0000000039010: VISA Loyalty +A000000003999910: VISA Proprietary ATM +A00000000401: MasterCard PayPass +A0000000041010: MasterCard Global +A00000000410101213: MasterCard Credit +A00000000410101215: MasterCard Credit +A0000000042010: MasterCard Specific +A0000000043010: MasterCard Specific +A0000000043060: Maestro (Debit) +A000000004306001: Maestro (Debit) +A0000000044010: MasterCard Specific +A0000000045010: MasterCard Specific +A0000000046000: Cirrus +A0000000048002: SecureCode EMV-CAP +A0000000049999: MasterCard PayPass +A0000000050001: Maestro UK +A0000000050002: Solo +A00000002401: Self Service +A000000025: American Express +A0000000250000: American Express +A00000002501: American Express +A000000025010402: American Express +A000000025010701: ExpressPay +A000000025010801: American Express +A0000000291010: Link / American Express +A0000000421010: Cartes Bancaire EMV Card +A0000000426010: Apple Pay +A00000006510: JCB +A0000000651010: JCB J Smart Credit +A00000006900: Moneo +A000000077010000021000000000003B: Visa AEPN +A000000098: Debit Card +A0000000980848: Debit Card +A0000001211010: Dankort VISA GEM Vision +A0000001410001: PagoBANCOMAT +A0000001523010: Discover, Pulse D Pas +A0000001524010: Discover +A0000001544442: Banricompras Debito +A000000172950001: BAROC Taiwan +A0000002281010: SPAN (M/Chip) +A0000002282010: SPAN (VIS) +A0000002771010: INTERAC +A00000031510100528: Currence PuC +A0000003156020: Chipknip +A0000003591010028001: Girocard EAPS +A0000003710001: InterSwitch Verve Card +A0000004540010: Etranzact Genesis Card +A0000004540011: Etranzact Genesis Card 2 +A0000004766C: GOOGLE_PAYMENT +A0000005241010: RuPay +A0000006723010: TROY chip credit card +A0000006723020: TROY chip debit card +A0000007705850: XTRAPOWER +B012345678: Maestro TEST +D27600002545500100: Girocard +D5780000021010: Bankaxept +F0000000030001: BRADESCO +A000000003000000: (VISA) Card Manager +A000000003534441: Schlumberger SD +A0000000035350: Security Domain +A000000003535041: Security Domain +A0000000040000: MasterCard Card Manager +A000000018434D: Gemplus card manager +A000000018434D00: Gemplus Security Domain +A0000000960200: Proton WISD +A0000001510000: Global Platform SD +A00000015153504341534400: CASD_AID +A000000476A010: GSD_MANAGER_AID +A000000476A110: GSD_MANAGER_AID +315041592E5359532E4444463031: Visa PSE +325041592E5359532E4444463031: Visa PPSE +A0000000042203: MasterCard Specific +A0000000045555: APDULogger +A0000000090001FF44FF1289: Orange +A0000000101030: Maestro-CH +A00000001800: Gemplus +A0000000181001: gemplus util packages +A000000025010104: American Express +A00000002949034010100001: HSBC +A00000002949282010100000: Barclay +A00000005945430100: Girocard Electronic Cash +A0000000980840: Visa Common Debit +A0000001570010: AMEX +A0000001570020: MasterCard +A0000001570021: Maestro +A0000001570022: Maestro +A0000001570023: CASH +A0000001570030: VISA +A0000001570031: VISA +A0000001570040: JCB +A0000001570050: Postcard +A0000001570051: Postcard +A0000001570100: MCard +A0000001570104: MyOne +A000000157010C: WIRCard +A000000157010D: Power Card +A0000001574443: DINERS CLUB +A0000001574444: Supercard Plus +A00000022820101010: SPAN +A000000308000010000100: ID-ONE PIV BIO +A0000003241010: Discover Zip +A000000333010101: UnionPay Debit +A000000333010102: UnionPay Credit +A000000333010103: UnionPay Quasi Credit +A000000333010106: UnionPay Electronic Cash +A000000333010108: U.S. UnionPay Common Debit +A000000337102000: Classic +A000000337101001: Prepaye Online +A000000337102001: Prepaye Possibile Offiline +A000000337601001: Porte Monnaie Electronique +A0000006581010: MIR Credit +A0000006581011: MIR Credit +A0000006582010: MIR Debit +D040000001000002: Paylife Quick IEP +D040000002000002: RFU +D040000003000002: POS +D040000004000002: ATM +D04000000B000002: Retail +D04000000C000002: Bank_Data +D04000000D000002: Shopping +D040000013000001: DF_UNI_Kepler1 +D040000013000001: DF_Schüler1 +D040000013000002: DF_UNI_Kepler2 +D040000013000002: DF_Schüler2 +D040000014000001: DF_Mensa +D040000015000001: DF_UNI_Ausweis +D040000015000001: DF_Ausweis +D0400000190001: EMV ATM Maestro +D0400000190002: EMV POS Maestro +D0400000190003: EMV ATM MasterCard +D0400000190004: EMV POS MasterCard +D276000025: Girocard +D27600002547410100: Girocard ATM +D7560000010101: Reka Card +D7560000300101: M Budget \ No newline at end of file diff --git a/assets/resources/nfc/emv/country_code.nfc b/assets/resources/nfc/emv/country_code.nfc index e43c35f3..8b19ab83 100644 --- a/assets/resources/nfc/emv/country_code.nfc +++ b/assets/resources/nfc/emv/country_code.nfc @@ -1,249 +1,252 @@ -0004 AFG -0008 ALB -0010 ATA -0012 DZA -0016 ASM -0020 AND -0024 AGO -0028 ATG -0031 AZE -0032 ARG -0036 AUS -0040 AUT -0044 BHS -0048 BHR -0050 BGD -0051 ARM -0052 BRB -0056 BEL -0060 BMU -0064 BTN -0068 BOL -0070 BIH -0072 BWA -0074 BVT -0076 BRA -0084 BLZ -0086 IOT -0090 SLB -0092 VGB -0096 BRN -0100 BGR -0104 MMR -0108 BDI -0112 BLR -0116 KHM -0120 CMR -0124 CAN -0132 CPV -0136 CYM -0140 CAF -0144 LKA -0148 TCD -0152 CHL -0156 CHN -0158 TWN -0162 CXR -0166 CCK -0170 COL -0174 COM -0175 MYT -0178 COG -0180 COD -0184 COK -0188 CRI -0191 HRV -0192 CUB -0196 CYP -0203 CZE -0204 BEN -0208 DNK -0212 DMA -0214 DOM -0218 ECU -0222 SLV -0226 GNQ -0231 ETH -0232 ERI -0233 EST -0234 FRO -0238 FLK -0239 SGS -0242 FJI -0246 FIN -0248 ALA -0250 FRA -0254 GUF -0258 PYF -0260 ATF -0262 DJI -0266 GAB -0268 GEO -0270 GMB -0275 PSE -0276 DEU -0288 GHA -0292 GIB -0296 KIR -0300 GRC -0304 GRL -0308 GRD -0312 GLP -0316 GUM -0320 GTM -0324 GIN -0328 GUY -0332 HTI -0334 HMD -0336 VAT -0340 HND -0344 HKG -0348 HUN -0352 ISL -0356 IND -0360 IDN -0364 IRN -0368 IRQ -0372 IRL -0376 ISR -0380 ITA -0384 CIV -0388 JAM -0392 JPN -0398 KAZ -0400 JOR -0404 KEN -0408 PRK -0410 KOR -0414 KWT -0417 KGZ -0418 LAO -0422 LBN -0426 LSO -0428 LVA -0430 LBR -0434 LBY -0438 LIE -0440 LTU -0442 LUX -0446 MAC -0450 MDG -0454 MWI -0458 MYS -0462 MDV -0466 MLI -0470 MLT -0474 MTQ -0478 MRT -0480 MUS -0484 MEX -0492 MCO -0496 MNG -0498 MDA -0499 MNE -0500 MSR -0504 MAR -0508 MOZ -0512 OMN -0516 NAM -0520 NRU -0524 NPL -0528 NLD -0531 CUW -0533 ABW -0534 SXM -0535 BES -0540 NCL -0548 VUT -0554 NZL -0558 NIC -0562 NER -0566 NGA -0570 NIU -0574 NFK -0578 NOR -0580 MNP -0581 UMI -0583 FSM -0584 MHL -0585 PLW -0586 PAK -0591 PAN -0598 PNG -0600 PRY -0604 PER -0608 PHL -0612 PCN -0616 POL -0620 PRT -0624 GNB -0626 TLS -0630 PRI -0634 QAT -0638 REU -0642 ROU -0643 RUS -0646 RWA -0652 BLM -0654 SHN -0659 KNA -0660 AIA -0662 LCA -0663 MAF -0666 SPM -0670 VCT -0674 SMR -0678 STP -0682 SAU -0686 SEN -0688 SRB -0690 SYC -0694 SLE -0702 SGP -0703 SVK -0704 VNM -0705 SVN -0706 SOM -0710 ZAF -0716 ZWE -0724 ESP -0728 SSD -0729 SDN -0732 ESH -0740 SUR -0744 SJM -0748 SWZ -0752 SWE -0756 CHE -0760 SYR -0762 TJK -0764 THA -0768 TGO -0772 TKL -0776 TON -0780 TTO -0784 ARE -0788 TUN -0792 TUR -0795 TKM -0796 TCA -0798 TUV -0800 UGA -0804 UKR -0807 MKD -0818 EGY -0826 GBR -0831 GGY -0832 JEY -0833 IMN -0834 TZA -0840 USA -0850 VIR -0854 BFA -0858 URY -0860 UZB -0862 VEN -0876 WLF -0882 WSM -0887 YEM -0894 ZMB \ No newline at end of file +Filetype: Flipper EMV resources +Version: 1 +# EMV country code: country name +0004: AFG +0008: ALB +0010: ATA +0012: DZA +0016: ASM +0020: AND +0024: AGO +0028: ATG +0031: AZE +0032: ARG +0036: AUS +0040: AUT +0044: BHS +0048: BHR +0050: BGD +0051: ARM +0052: BRB +0056: BEL +0060: BMU +0064: BTN +0068: BOL +0070: BIH +0072: BWA +0074: BVT +0076: BRA +0084: BLZ +0086: IOT +0090: SLB +0092: VGB +0096: BRN +0100: BGR +0104: MMR +0108: BDI +0112: BLR +0116: KHM +0120: CMR +0124: CAN +0132: CPV +0136: CYM +0140: CAF +0144: LKA +0148: TCD +0152: CHL +0156: CHN +0158: TWN +0162: CXR +0166: CCK +0170: COL +0174: COM +0175: MYT +0178: COG +0180: COD +0184: COK +0188: CRI +0191: HRV +0192: CUB +0196: CYP +0203: CZE +0204: BEN +0208: DNK +0212: DMA +0214: DOM +0218: ECU +0222: SLV +0226: GNQ +0231: ETH +0232: ERI +0233: EST +0234: FRO +0238: FLK +0239: SGS +0242: FJI +0246: FIN +0248: ALA +0250: FRA +0254: GUF +0258: PYF +0260: ATF +0262: DJI +0266: GAB +0268: GEO +0270: GMB +0275: PSE +0276: DEU +0288: GHA +0292: GIB +0296: KIR +0300: GRC +0304: GRL +0308: GRD +0312: GLP +0316: GUM +0320: GTM +0324: GIN +0328: GUY +0332: HTI +0334: HMD +0336: VAT +0340: HND +0344: HKG +0348: HUN +0352: ISL +0356: IND +0360: IDN +0364: IRN +0368: IRQ +0372: IRL +0376: ISR +0380: ITA +0384: CIV +0388: JAM +0392: JPN +0398: KAZ +0400: JOR +0404: KEN +0408: PRK +0410: KOR +0414: KWT +0417: KGZ +0418: LAO +0422: LBN +0426: LSO +0428: LVA +0430: LBR +0434: LBY +0438: LIE +0440: LTU +0442: LUX +0446: MAC +0450: MDG +0454: MWI +0458: MYS +0462: MDV +0466: MLI +0470: MLT +0474: MTQ +0478: MRT +0480: MUS +0484: MEX +0492: MCO +0496: MNG +0498: MDA +0499: MNE +0500: MSR +0504: MAR +0508: MOZ +0512: OMN +0516: NAM +0520: NRU +0524: NPL +0528: NLD +0531: CUW +0533: ABW +0534: SXM +0535: BES +0540: NCL +0548: VUT +0554: NZL +0558: NIC +0562: NER +0566: NGA +0570: NIU +0574: NFK +0578: NOR +0580: MNP +0581: UMI +0583: FSM +0584: MHL +0585: PLW +0586: PAK +0591: PAN +0598: PNG +0600: PRY +0604: PER +0608: PHL +0612: PCN +0616: POL +0620: PRT +0624: GNB +0626: TLS +0630: PRI +0634: QAT +0638: REU +0642: ROU +0643: RUS +0646: RWA +0652: BLM +0654: SHN +0659: KNA +0660: AIA +0662: LCA +0663: MAF +0666: SPM +0670: VCT +0674: SMR +0678: STP +0682: SAU +0686: SEN +0688: SRB +0690: SYC +0694: SLE +0702: SGP +0703: SVK +0704: VNM +0705: SVN +0706: SOM +0710: ZAF +0716: ZWE +0724: ESP +0728: SSD +0729: SDN +0732: ESH +0740: SUR +0744: SJM +0748: SWZ +0752: SWE +0756: CHE +0760: SYR +0762: TJK +0764: THA +0768: TGO +0772: TKL +0776: TON +0780: TTO +0784: ARE +0788: TUN +0792: TUR +0795: TKM +0796: TCA +0798: TUV +0800: UGA +0804: UKR +0807: MKD +0818: EGY +0826: GBR +0831: GGY +0832: JEY +0833: IMN +0834: TZA +0840: USA +0850: VIR +0854: BFA +0858: URY +0860: UZB +0862: VEN +0876: WLF +0882: WSM +0887: YEM +0894: ZMB \ No newline at end of file diff --git a/assets/resources/nfc/emv/currency_code.nfc b/assets/resources/nfc/emv/currency_code.nfc index 4ee69181..31c575b3 100644 --- a/assets/resources/nfc/emv/currency_code.nfc +++ b/assets/resources/nfc/emv/currency_code.nfc @@ -1,168 +1,171 @@ -0997 USN -0994 XSU -0990 CLF -0986 BRL -0985 PLN -0984 BOV -0981 GEL -0980 UAH -0979 MXV -0978 EUR -0977 BAM -0976 CDF -0975 BGN -0973 AOA -0972 TJS -0971 AFN -0970 COU -0969 MGA -0968 SRD -0967 ZMW -0965 XUA -0960 XDR -0953 XPF -0952 XOF -0951 XCD -0950 XAF -0949 TRY -0948 CHW -0947 CHE -0946 RON -0944 AZN -0943 MZN -0941 RSD -0940 UYI -0938 SDG -0937 VEF -0936 GHS -0934 TMT -0933 BYN -0932 ZWL -0931 CUC -0930 STN -0929 MRU -0901 TWD -0886 YER -0882 WST -0860 UZS -0858 UYU -0840 USD -0834 TZS -0826 GBP -0818 EGP -0807 MKD -0800 UGX -0788 TND -0784 AED -0780 TTD -0776 TOP -0764 THB -0760 SYP -0756 CHF -0752 SEK -0748 SZL -0728 SSP -0710 ZAR -0706 SOS -0704 VND -0702 SGD -0694 SLL -0690 SCR -0682 SAR -0654 SHP -0646 RWF -0643 RUB -0634 QAR -0608 PHP -0604 PEN -0600 PYG -0598 PGK -0590 PAB -0586 PKR -0578 NOK -0566 NGN -0558 NIO -0554 NZD -0548 VUV -0533 AWG -0532 ANG -0524 NPR -0516 NAD -0512 OMR -0504 MAD -0498 MDL -0496 MNT -0484 MXN -0480 MUR -0462 MVR -0458 MYR -0454 MWK -0446 MOP -0434 LYD -0430 LRD -0426 LSL -0422 LBP -0418 LAK -0417 KGS -0414 KWD -0410 KRW -0408 KPW -0404 KES -0400 JOD -0398 KZT -0392 JPY -0388 JMD -0376 ILS -0368 IQD -0364 IRR -0360 IDR -0356 INR -0352 ISK -0348 HUF -0344 HKD -0340 HNL -0332 HTG -0328 GYD -0324 GNF -0320 GTQ -0292 GIP -0270 GMD -0262 DJF -0242 FJD -0238 FKP -0232 ERN -0230 ETB -0222 SVC -0214 DOP -0208 DKK -0203 CZK -0192 CUP -0191 HRK -0188 CRC -0174 KMF -0170 COP -0156 CNY -0152 CLP -0144 LKR -0136 KYD -0132 CVE -0124 CAD -0116 KHR -0108 BIF -0104 MMK -0096 BND -0090 SBD -0084 BZD -0072 BWP -0068 BOB -0064 BTN -0060 BMD -0052 BBD -0051 AMD -0050 BDT -0048 BHD -0044 BSD -0036 AUD -0032 ARS -0012 DZD -0008 ALL \ No newline at end of file +Filetype: Flipper EMV resources +Version: 1 +# EMV currency code: currency name +0997: USN +0994: XSU +0990: CLF +0986: BRL +0985: PLN +0984: BOV +0981: GEL +0980: UAH +0979: MXV +0978: EUR +0977: BAM +0976: CDF +0975: BGN +0973: AOA +0972: TJS +0971: AFN +0970: COU +0969: MGA +0968: SRD +0967: ZMW +0965: XUA +0960: XDR +0953: XPF +0952: XOF +0951: XCD +0950: XAF +0949: TRY +0948: CHW +0947: CHE +0946: RON +0944: AZN +0943: MZN +0941: RSD +0940: UYI +0938: SDG +0937: VEF +0936: GHS +0934: TMT +0933: BYN +0932: ZWL +0931: CUC +0930: STN +0929: MRU +0901: TWD +0886: YER +0882: WST +0860: UZS +0858: UYU +0840: USD +0834: TZS +0826: GBP +0818: EGP +0807: MKD +0800: UGX +0788: TND +0784: AED +0780: TTD +0776: TOP +0764: THB +0760: SYP +0756: CHF +0752: SEK +0748: SZL +0728: SSP +0710: ZAR +0706: SOS +0704: VND +0702: SGD +0694: SLL +0690: SCR +0682: SAR +0654: SHP +0646: RWF +0643: RUB +0634: QAR +0608: PHP +0604: PEN +0600: PYG +0598: PGK +0590: PAB +0586: PKR +0578: NOK +0566: NGN +0558: NIO +0554: NZD +0548: VUV +0533: AWG +0532: ANG +0524: NPR +0516: NAD +0512: OMR +0504: MAD +0498: MDL +0496: MNT +0484: MXN +0480: MUR +0462: MVR +0458: MYR +0454: MWK +0446: MOP +0434: LYD +0430: LRD +0426: LSL +0422: LBP +0418: LAK +0417: KGS +0414: KWD +0410: KRW +0408: KPW +0404: KES +0400: JOD +0398: KZT +0392: JPY +0388: JMD +0376: ILS +0368: IQD +0364: IRR +0360: IDR +0356: INR +0352: ISK +0348: HUF +0344: HKD +0340: HNL +0332: HTG +0328: GYD +0324: GNF +0320: GTQ +0292: GIP +0270: GMD +0262: DJF +0242: FJD +0238: FKP +0232: ERN +0230: ETB +0222: SVC +0214: DOP +0208: DKK +0203: CZK +0192: CUP +0191: HRK +0188: CRC +0174: KMF +0170: COP +0156: CNY +0152: CLP +0144: LKR +0136: KYD +0132: CVE +0124: CAD +0116: KHR +0108: BIF +0104: MMK +0096: BND +0090: SBD +0084: BZD +0072: BWP +0068: BOB +0064: BTN +0060: BMD +0052: BBD +0051: AMD +0050: BDT +0048: BHD +0044: BSD +0036: AUD +0032: ARS +0012: DZD +0008: ALL \ No newline at end of file diff --git a/core/flipper.c b/core/flipper.c index c8d12068..59c1823a 100755 --- a/core/flipper.c +++ b/core/flipper.c @@ -3,10 +3,12 @@ #include #include +#define TAG "Flipper" + static void flipper_print_version(const char* target, const Version* version) { if(version) { FURI_LOG_I( - "FLIPPER", + TAG, "\r\n\t%s version:\t%s\r\n" "\tBuild date:\t\t%s\r\n" "\tGit Commit:\t\t%s (%s)\r\n" @@ -18,7 +20,7 @@ static void flipper_print_version(const char* target, const Version* version) { version_get_gitbranchnum(version), version_get_gitbranch(version)); } else { - FURI_LOG_I("FLIPPER", "No build info for %s", target); + FURI_LOG_I(TAG, "No build info for %s", target); } } @@ -31,10 +33,10 @@ void flipper_init() { version = (const Version*)furi_hal_version_get_firmware_version(); flipper_print_version("Firmware", version); - FURI_LOG_I("FLIPPER", "starting services"); + FURI_LOG_I(TAG, "starting services"); for(size_t i = 0; i < FLIPPER_SERVICES_COUNT; i++) { - FURI_LOG_I("FLIPPER", "starting service %s", FLIPPER_SERVICES[i].name); + FURI_LOG_I(TAG, "starting service %s", FLIPPER_SERVICES[i].name); FuriThread* thread = furi_thread_alloc(); @@ -45,5 +47,5 @@ void flipper_init() { furi_thread_start(thread); } - FURI_LOG_I("FLIPPER", "services startup complete"); + FURI_LOG_I(TAG, "services startup complete"); } diff --git a/core/furi/common_defines.h b/core/furi/common_defines.h old mode 100644 new mode 100755 index bb4aadfa..00a68529 --- a/core/furi/common_defines.h +++ b/core/furi/common_defines.h @@ -64,4 +64,10 @@ #ifndef TOSTRING #define TOSTRING(x) STRINGIFY(x) +#endif + +#ifndef REVERSE_BYTES_U32 +#define REVERSE_BYTES_U32(x) \ + ((((x)&0x000000FF) << 24) | (((x)&0x0000FF00) << 8) | (((x)&0x00FF0000) >> 8) | \ + (((x)&0xFF000000) >> 24)) #endif \ No newline at end of file diff --git a/firmware/targets/f6/Inc/FreeRTOSConfig.h b/firmware/targets/f6/Inc/FreeRTOSConfig.h index 228b530d..1ad20993 100644 --- a/firmware/targets/f6/Inc/FreeRTOSConfig.h +++ b/firmware/targets/f6/Inc/FreeRTOSConfig.h @@ -57,7 +57,7 @@ #endif /* CMSIS_device_header */ #define configENABLE_FPU 1 -#define configENABLE_MPU 1 +#define configENABLE_MPU 0 #define configUSE_PREEMPTION 1 #define configSUPPORT_STATIC_ALLOCATION 0 @@ -101,6 +101,9 @@ #define configTIMER_TASK_PRIORITY ( 2 ) #define configTIMER_QUEUE_LENGTH 32 #define configTIMER_TASK_STACK_DEPTH 256 +#define configTIMER_SERVICE_TASK_NAME "TimersSrv" + +#define configIDLE_TASK_NAME "(-_-)" /* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */ diff --git a/firmware/targets/f6/Inc/stm32_assert.h b/firmware/targets/f6/Inc/stm32_assert.h new file mode 100644 index 00000000..9f6261ff --- /dev/null +++ b/firmware/targets/f6/Inc/stm32_assert.h @@ -0,0 +1,40 @@ +/** + ****************************************************************************** + * @file stm32_assert.h + * @brief STM32 assert file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32_ASSERT_H +#define __STM32_ASSERT_H + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef USE_FULL_ASSERT + #define assert_param(expr) ((expr) ? (void)0U : assert_failed()) + void assert_failed(); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32_ASSERT_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f6/Inc/stm32wbxx_hal_conf.h b/firmware/targets/f6/Inc/stm32wbxx_hal_conf.h index ab7b2953..4d5ad791 100644 --- a/firmware/targets/f6/Inc/stm32wbxx_hal_conf.h +++ b/firmware/targets/f6/Inc/stm32wbxx_hal_conf.h @@ -184,7 +184,7 @@ * @brief Uncomment the line below to expanse the "assert_param" macro in the * HAL drivers code */ -/* #define USE_FULL_ASSERT 1U */ +#define USE_FULL_ASSERT 1U /* ################## SPI peripheral configuration ########################## */ @@ -329,17 +329,8 @@ /* Exported macro ------------------------------------------------------------*/ #ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); + #define assert_param(expr) ((expr) ? (void)0U : assert_failed()) + void assert_failed(); #else #define assert_param(expr) ((void)0U) #endif /* USE_FULL_ASSERT */ diff --git a/firmware/targets/f6/Src/main.c b/firmware/targets/f6/Src/main.c index ea6d8943..a546086f 100644 --- a/firmware/targets/f6/Src/main.c +++ b/firmware/targets/f6/Src/main.c @@ -1,11 +1,11 @@ #include "main.h" -#include "fatfs/fatfs.h" - #include #include #include +#define TAG "Main" + int main(void) { // Initialize FURI layer furi_init(); @@ -16,13 +16,9 @@ int main(void) { // Flipper FURI HAL furi_hal_init(); - // 3rd party - MX_FATFS_Init(); - FURI_LOG_I("HAL", "FATFS OK"); - // CMSIS initialization osKernelInitialize(); - FURI_LOG_I("HAL", "KERNEL OK"); + FURI_LOG_I(TAG, "KERNEL OK"); // Init flipper flipper_init(); @@ -47,9 +43,6 @@ void Error_Handler(void) { * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { - /* USER CODE BEGIN 6 */ - /* User can add his own implementation to report the file name and line number, - tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ - /* USER CODE END 6 */ + furi_crash("HAL assert failed"); } #endif /* USE_FULL_ASSERT */ diff --git a/firmware/targets/f6/ble-glue/battery_service.c b/firmware/targets/f6/ble-glue/battery_service.c index 1dd8c5a0..2a5dad5e 100644 --- a/firmware/targets/f6/ble-glue/battery_service.c +++ b/firmware/targets/f6/ble-glue/battery_service.c @@ -4,7 +4,7 @@ #include -#define BATTERY_SERVICE_TAG "battery service" +#define TAG "BtBatterySvc" typedef struct { uint16_t svc_handle; @@ -23,7 +23,7 @@ void battery_svc_start() { // Add Battery service status = aci_gatt_add_service(UUID_TYPE_16, (Service_UUID_t*)&service_uuid, PRIMARY_SERVICE, 4, &battery_svc->svc_handle); if(status) { - FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed to add Battery service: %d", status); + FURI_LOG_E(TAG, "Failed to add Battery service: %d", status); } // Add Battery level characteristic status = aci_gatt_add_char(battery_svc->svc_handle, @@ -37,7 +37,7 @@ void battery_svc_start() { CHAR_VALUE_LEN_CONSTANT, &battery_svc->char_level_handle); if(status) { - FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed to add Battery level characteristic: %d", status); + FURI_LOG_E(TAG, "Failed to add Battery level characteristic: %d", status); } } @@ -47,12 +47,12 @@ void battery_svc_stop() { // Delete Battery level characteristic status = aci_gatt_del_char(battery_svc->svc_handle, battery_svc->char_level_handle); if(status) { - FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed to delete Battery level characteristic: %d", status); + FURI_LOG_E(TAG, "Failed to delete Battery level characteristic: %d", status); } // Delete Battery service status = aci_gatt_del_service(battery_svc->svc_handle); if(status) { - FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed to delete Battery service: %d", status); + FURI_LOG_E(TAG, "Failed to delete Battery service: %d", status); } free(battery_svc); battery_svc = NULL; @@ -65,14 +65,14 @@ bool battery_svc_update_level(uint8_t battery_charge) { return false; } // Update battery level characteristic - FURI_LOG_I(BATTERY_SERVICE_TAG, "Updating battery level characteristic"); + FURI_LOG_I(TAG, "Updating battery level characteristic"); tBleStatus result = aci_gatt_update_char_value(battery_svc->svc_handle, battery_svc->char_level_handle, 0, 1, &battery_charge); if(result) { - FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed updating RX characteristic: %d", result); + FURI_LOG_E(TAG, "Failed updating RX characteristic: %d", result); } return result != BLE_STATUS_SUCCESS; } diff --git a/firmware/targets/f6/ble-glue/ble_app.c b/firmware/targets/f6/ble-glue/ble_app.c index 33e5264a..40b34679 100644 --- a/firmware/targets/f6/ble-glue/ble_app.c +++ b/firmware/targets/f6/ble-glue/ble_app.c @@ -8,7 +8,7 @@ #include -#define BLE_APP_TAG "ble app" +#define TAG "Bt" PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static TL_CmdPacket_t ble_app_cmd_buffer; PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint32_t ble_app_nvm[BLE_NVM_SRAM_SIZE]; @@ -33,7 +33,7 @@ bool ble_app_init() { ble_app->hci_mtx = osMutexNew(NULL); ble_app->hci_sem = osSemaphoreNew(1, 0, NULL); // HCI transport layer thread to handle user asynch events - ble_app->hci_thread_attr.name = "ble hci"; + ble_app->hci_thread_attr.name = "BleHciWorker"; ble_app->hci_thread_attr.stack_size = 1024; ble_app->hci_thread_id = osThreadNew(ble_app_hci_thread, NULL, &ble_app->hci_thread_attr); @@ -53,7 +53,7 @@ bool ble_app_init() { }; status = SHCI_C2_Config(&config_param); if(status) { - FURI_LOG_E(BLE_APP_TAG, "Failed to configure 2nd core: %d", status); + FURI_LOG_E(TAG, "Failed to configure 2nd core: %d", status); } // Start ble stack on 2nd core @@ -82,7 +82,7 @@ bool ble_app_init() { }; status = SHCI_C2_BLE_Init(&ble_init_cmd_packet); if(status) { - FURI_LOG_E(BLE_APP_TAG, "Failed to start ble stack: %d", status); + FURI_LOG_E(TAG, "Failed to start ble stack: %d", status); } return status == SHCI_Success; } diff --git a/firmware/targets/f6/ble-glue/ble_glue.c b/firmware/targets/f6/ble-glue/ble_glue.c index 4a9c144e..45503683 100644 --- a/firmware/targets/f6/ble-glue/ble_glue.c +++ b/firmware/targets/f6/ble-glue/ble_glue.c @@ -10,6 +10,8 @@ #include "app_debug.h" #include +#define TAG "Core2" + #define POOL_SIZE (CFG_TLBLE_EVT_QUEUE_LENGTH*4U*DIVC(( sizeof(TL_PacketHeader_t) + TL_BLE_EVENT_FRAME_SIZE ), 4U)) PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_event_pool[POOL_SIZE]; @@ -17,6 +19,16 @@ PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t ble_glue_system_cmd_b PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_system_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255U]; PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_ble_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255]; +typedef enum { + // Stage 1: core2 startup and FUS + BleGlueStatusStartup, + BleGlueStatusBroken, + BleGlueStatusFusStarted, + // Stage 2: radio stack + BleGlueStatusRadioStackStarted, + BleGlueStatusRadioStackMissing +} BleGlueStatus; + typedef struct { osMutexId_t shci_mtx; osSemaphoreId_t shci_sem; @@ -33,13 +45,6 @@ static void ble_glue_user_event_thread(void *argument); static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status); static void ble_glue_sys_user_event_callback(void* pPayload); -BleGlueStatus ble_glue_get_status() { - if(!ble_glue) { - return BleGlueStatusUninitialized; - } - return ble_glue->status; -} - void ble_glue_set_key_storage_changed_callback(BleGlueKeyStorageChangedCallback callback, void* context) { furi_assert(ble_glue); furi_assert(callback); @@ -50,7 +55,7 @@ void ble_glue_set_key_storage_changed_callback(BleGlueKeyStorageChangedCallback void ble_glue_init() { ble_glue = furi_alloc(sizeof(BleGlue)); ble_glue->status = BleGlueStatusStartup; - ble_glue->shci_user_event_thread_attr.name = "ble_shci_evt"; + ble_glue->shci_user_event_thread_attr.name = "BleShciWorker"; ble_glue->shci_user_event_thread_attr.stack_size = 1024; // Configure the system Power Mode @@ -94,6 +99,68 @@ void ble_glue_init() { */ } +static bool ble_glue_wait_status(BleGlueStatus status) { + bool ret = false; + size_t countdown = 1000; + while (countdown > 0) { + if (ble_glue->status == status) { + ret = true; + break; + } + countdown--; + osDelay(1); + } + return ret; +} + +bool ble_glue_start() { + furi_assert(ble_glue); + + if (!ble_glue_wait_status(BleGlueStatusFusStarted)) { + // shutdown core2 power + FURI_LOG_E(TAG, "Core2 catastrophic failure, cutting its power"); + LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); + ble_glue->status = BleGlueStatusBroken; + furi_hal_power_insomnia_exit(); + return false; + } + + bool ret = false; + furi_hal_power_insomnia_enter(); + if(ble_app_init()) { + FURI_LOG_I(TAG, "Radio stack started"); + ble_glue->status = BleGlueStatusRadioStackStarted; + ret = true; + if(SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7) == SHCI_Success) { + FURI_LOG_I(TAG, "Flash activity control switched to SEM7"); + } else { + FURI_LOG_E(TAG, "Failed to switch flash activity control to SEM7"); + } + } else { + FURI_LOG_E(TAG, "Radio stack startup failed"); + ble_glue->status = BleGlueStatusRadioStackMissing; + } + furi_hal_power_insomnia_exit(); + + return ret; +} + +bool ble_glue_is_alive() { + if(!ble_glue) { + return false; + } + + return ble_glue->status >= BleGlueStatusFusStarted; +} + +bool ble_glue_is_radio_stack_ready() { + if(!ble_glue) { + return false; + } + + return ble_glue->status == BleGlueStatusRadioStackStarted; +} + static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status) { switch (status) { case SHCI_TL_CmdBusy: @@ -124,21 +191,11 @@ static void ble_glue_sys_user_event_callback( void * pPayload ) { TL_AsynchEvt_t *p_sys_event = (TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload); if(p_sys_event->subevtcode == SHCI_SUB_EVT_CODE_READY) { - if(ble_app_init()) { - FURI_LOG_I("Core2", "BLE stack started"); - ble_glue->status = BleGlueStatusStarted; - if(SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7) == SHCI_Success) { - FURI_LOG_I("Core2", "Flash activity control switched to SEM7"); - } else { - FURI_LOG_E("Core2", "Failed to switch flash activity control to SEM7"); - } - } else { - FURI_LOG_E("Core2", "BLE stack startup failed"); - ble_glue->status = BleGlueStatusBleStackMissing; - } + FURI_LOG_I(TAG, "Fus started"); + ble_glue->status = BleGlueStatusFusStarted; furi_hal_power_insomnia_exit(); } else if(p_sys_event->subevtcode == SHCI_SUB_EVT_ERROR_NOTIF) { - FURI_LOG_E("Core2", "Error during initialization"); + FURI_LOG_E(TAG, "Error during initialization"); furi_hal_power_insomnia_exit(); } else if(p_sys_event->subevtcode == SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE) { SHCI_C2_BleNvmRamUpdate_Evt_t* p_sys_ble_nvm_ram_update_event = (SHCI_C2_BleNvmRamUpdate_Evt_t*)p_sys_event->payload; diff --git a/firmware/targets/f6/ble-glue/ble_glue.h b/firmware/targets/f6/ble-glue/ble_glue.h index e9d6c03f..ac668c42 100644 --- a/firmware/targets/f6/ble-glue/ble_glue.h +++ b/firmware/targets/f6/ble-glue/ble_glue.h @@ -1,6 +1,7 @@ #pragma once #include +#include #ifdef __cplusplus extern "C" { @@ -8,17 +9,33 @@ extern "C" { typedef void(*BleGlueKeyStorageChangedCallback)(uint8_t* change_addr_start, uint16_t size, void* context); -typedef enum { - BleGlueStatusUninitialized, - BleGlueStatusStartup, - BleGlueStatusBleStackMissing, - BleGlueStatusStarted -} BleGlueStatus; +/** Initialize start core2 and initialize transport */ void ble_glue_init(); -BleGlueStatus ble_glue_get_status(); +/** Start Core2 Radio stack + * + * @return true on success + */ +bool ble_glue_start(); +/** Is core2 alive and at least FUS is running + * + * @return true if core2 is alive + */ +bool ble_glue_is_alive(); + +/** Is core2 radio stack present and ready + * + * @return true if present and ready + */ +bool ble_glue_is_radio_stack_ready(); + +/** Set callback for NVM in RAM changes + * + * @param[in] callback The callback to call on NVM change + * @param context The context for callback + */ void ble_glue_set_key_storage_changed_callback(BleGlueKeyStorageChangedCallback callback, void* context); #ifdef __cplusplus diff --git a/firmware/targets/f6/ble-glue/dev_info_service.c b/firmware/targets/f6/ble-glue/dev_info_service.c index 7ce2647c..64ff0509 100644 --- a/firmware/targets/f6/ble-glue/dev_info_service.c +++ b/firmware/targets/f6/ble-glue/dev_info_service.c @@ -4,7 +4,7 @@ #include -#define DEV_INFO_SVC_TAG "dev info service" +#define TAG "BtDevInfoSvc" typedef struct { uint16_t service_handle; @@ -29,7 +29,7 @@ void dev_info_svc_start() { uint16_t uuid = DEVICE_INFORMATION_SERVICE_UUID; status = aci_gatt_add_service(UUID_TYPE_16, (Service_UUID_t*)&uuid, PRIMARY_SERVICE, 9, &dev_info_svc->service_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add Device Information Service: %d", status); + FURI_LOG_E(TAG, "Failed to add Device Information Service: %d", status); } // Add characteristics @@ -45,7 +45,7 @@ void dev_info_svc_start() { CHAR_VALUE_LEN_CONSTANT, &dev_info_svc->man_name_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add manufacturer name char: %d", status); + FURI_LOG_E(TAG, "Failed to add manufacturer name char: %d", status); } uuid = SERIAL_NUMBER_UUID; status = aci_gatt_add_char(dev_info_svc->service_handle, @@ -59,7 +59,7 @@ void dev_info_svc_start() { CHAR_VALUE_LEN_CONSTANT, &dev_info_svc->serial_num_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add serial number char: %d", status); + FURI_LOG_E(TAG, "Failed to add serial number char: %d", status); } uuid = FIRMWARE_REVISION_UUID; status = aci_gatt_add_char(dev_info_svc->service_handle, @@ -73,7 +73,7 @@ void dev_info_svc_start() { CHAR_VALUE_LEN_CONSTANT, &dev_info_svc->firmware_rev_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add firmware revision char: %d", status); + FURI_LOG_E(TAG, "Failed to add firmware revision char: %d", status); } uuid = SOFTWARE_REVISION_UUID; status = aci_gatt_add_char(dev_info_svc->service_handle, @@ -87,7 +87,7 @@ void dev_info_svc_start() { CHAR_VALUE_LEN_CONSTANT, &dev_info_svc->software_rev_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add software revision char: %d", status); + FURI_LOG_E(TAG, "Failed to add software revision char: %d", status); } // Update characteristics @@ -97,7 +97,7 @@ void dev_info_svc_start() { strlen(dev_info_man_name), (uint8_t*)dev_info_man_name); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to update manufacturer name char: %d", status); + FURI_LOG_E(TAG, "Failed to update manufacturer name char: %d", status); } status = aci_gatt_update_char_value(dev_info_svc->service_handle, dev_info_svc->serial_num_char_handle, @@ -105,7 +105,7 @@ void dev_info_svc_start() { strlen(dev_info_serial_num), (uint8_t*)dev_info_serial_num); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to update serial number char: %d", status); + FURI_LOG_E(TAG, "Failed to update serial number char: %d", status); } status = aci_gatt_update_char_value(dev_info_svc->service_handle, dev_info_svc->firmware_rev_char_handle, @@ -113,7 +113,7 @@ void dev_info_svc_start() { strlen(dev_info_firmware_rev_num), (uint8_t*)dev_info_firmware_rev_num); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to update firmware revision char: %d", status); + FURI_LOG_E(TAG, "Failed to update firmware revision char: %d", status); } status = aci_gatt_update_char_value(dev_info_svc->service_handle, dev_info_svc->software_rev_char_handle, @@ -121,7 +121,7 @@ void dev_info_svc_start() { strlen(dev_info_software_rev_num), (uint8_t*)dev_info_software_rev_num); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to update software revision char: %d", status); + FURI_LOG_E(TAG, "Failed to update software revision char: %d", status); } } @@ -131,24 +131,24 @@ void dev_info_svc_stop() { // Delete service characteristics status = aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->man_name_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete manufacturer name char: %d", status); + FURI_LOG_E(TAG, "Failed to delete manufacturer name char: %d", status); } status = aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->serial_num_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete serial number char: %d", status); + FURI_LOG_E(TAG, "Failed to delete serial number char: %d", status); } status = aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->firmware_rev_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete firmware revision char: %d", status); + FURI_LOG_E(TAG, "Failed to delete firmware revision char: %d", status); } status = aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->software_rev_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete software revision char: %d", status); + FURI_LOG_E(TAG, "Failed to delete software revision char: %d", status); } // Delete service status = aci_gatt_del_service(dev_info_svc->service_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete device info service: %d", status); + FURI_LOG_E(TAG, "Failed to delete device info service: %d", status); } free(dev_info_svc); dev_info_svc = NULL; diff --git a/firmware/targets/f6/ble-glue/gap.c b/firmware/targets/f6/ble-glue/gap.c index 9ddae208..2fd29f10 100644 --- a/firmware/targets/f6/ble-glue/gap.c +++ b/firmware/targets/f6/ble-glue/gap.c @@ -10,7 +10,7 @@ #include -#define GAP_TAG "BLE" +#define TAG "BtGap" #define FAST_ADV_TIMEOUT 30000 #define INITIAL_ADV_TIMEOUT 60000 @@ -80,7 +80,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt ) if (disconnection_complete_event->Connection_Handle == gap->gap_svc.connection_handle) { gap->gap_svc.connection_handle = 0; gap->state = GapStateIdle; - FURI_LOG_I(GAP_TAG, "Disconnect from client. Reason: %d", disconnection_complete_event->Reason); + FURI_LOG_I(TAG, "Disconnect from client. Reason: %d", disconnection_complete_event->Reason); } if(gap->enable_adv) { // Restart advertising @@ -96,28 +96,28 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt ) meta_evt = (evt_le_meta_event*) event_pckt->data; switch (meta_evt->subevent) { case EVT_LE_CONN_UPDATE_COMPLETE: - FURI_LOG_D(GAP_TAG, "Connection update event"); + FURI_LOG_D(TAG, "Connection update event"); break; case EVT_LE_PHY_UPDATE_COMPLETE: evt_le_phy_update_complete = (hci_le_phy_update_complete_event_rp0*)meta_evt->data; if(evt_le_phy_update_complete->Status) { - FURI_LOG_E(GAP_TAG, "Update PHY failed, status %d", evt_le_phy_update_complete->Status); + FURI_LOG_E(TAG, "Update PHY failed, status %d", evt_le_phy_update_complete->Status); } else { - FURI_LOG_I(GAP_TAG, "Update PHY succeed"); + FURI_LOG_I(TAG, "Update PHY succeed"); } ret = hci_le_read_phy(gap->gap_svc.connection_handle,&tx_phy,&rx_phy); if(ret) { - FURI_LOG_E(GAP_TAG, "Read PHY failed, status: %d", ret); + FURI_LOG_E(TAG, "Read PHY failed, status: %d", ret); } else { - FURI_LOG_I(GAP_TAG, "PHY Params TX = %d, RX = %d ", tx_phy, rx_phy); + FURI_LOG_I(TAG, "PHY Params TX = %d, RX = %d ", tx_phy, rx_phy); } break; case EVT_LE_CONN_COMPLETE: furi_hal_power_insomnia_enter(); hci_le_connection_complete_event_rp0* connection_complete_event = (hci_le_connection_complete_event_rp0 *) meta_evt->data; - FURI_LOG_I(GAP_TAG, "Connection complete for connection handle 0x%x", connection_complete_event->Connection_Handle); + FURI_LOG_I(TAG, "Connection complete for connection handle 0x%x", connection_complete_event->Connection_Handle); // Stop advertising as connection completed osTimerStop(gap->advertise_timer); @@ -141,7 +141,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt ) aci_gap_pairing_complete_event_rp0 *pairing_complete; case EVT_BLUE_GAP_LIMITED_DISCOVERABLE: - FURI_LOG_I(GAP_TAG, "Limited discoverable event"); + FURI_LOG_I(TAG, "Limited discoverable event"); break; case EVT_BLUE_GAP_PASS_KEY_REQUEST: @@ -149,39 +149,39 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt ) // Generate random PIN code uint32_t pin = rand() % 999999; aci_gap_pass_key_resp(gap->gap_svc.connection_handle, pin); - FURI_LOG_I(GAP_TAG, "Pass key request event. Pin: %d", pin); + FURI_LOG_I(TAG, "Pass key request event. Pin: %d", pin); BleEvent event = {.type = BleEventTypePinCodeShow, .data.pin_code = pin}; gap->on_event_cb(event, gap->context); } break; case EVT_BLUE_GAP_AUTHORIZATION_REQUEST: - FURI_LOG_I(GAP_TAG, "Authorization request event"); + FURI_LOG_I(TAG, "Authorization request event"); break; case EVT_BLUE_GAP_SLAVE_SECURITY_INITIATED: - FURI_LOG_I(GAP_TAG, "Slave security initiated"); + FURI_LOG_I(TAG, "Slave security initiated"); break; case EVT_BLUE_GAP_BOND_LOST: - FURI_LOG_I(GAP_TAG, "Bond lost event. Start rebonding"); + FURI_LOG_I(TAG, "Bond lost event. Start rebonding"); aci_gap_allow_rebond(gap->gap_svc.connection_handle); break; case EVT_BLUE_GAP_DEVICE_FOUND: - FURI_LOG_I(GAP_TAG, "Device found event"); + FURI_LOG_I(TAG, "Device found event"); break; case EVT_BLUE_GAP_ADDR_NOT_RESOLVED: - FURI_LOG_I(GAP_TAG, "Address not resolved event"); + FURI_LOG_I(TAG, "Address not resolved event"); break; case EVT_BLUE_GAP_KEYPRESS_NOTIFICATION: - FURI_LOG_I(GAP_TAG, "Key press notification event"); + FURI_LOG_I(TAG, "Key press notification event"); break; case EVT_BLUE_GAP_NUMERIC_COMPARISON_VALUE: - FURI_LOG_I(GAP_TAG, "Hex_value = %lx", + FURI_LOG_I(TAG, "Hex_value = %lx", ((aci_gap_numeric_comparison_value_event_rp0 *)(blue_evt->data))->Numeric_Value); aci_gap_numeric_comparison_value_confirm_yesno(gap->gap_svc.connection_handle, 1); break; @@ -189,17 +189,17 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt ) case EVT_BLUE_GAP_PAIRING_CMPLT: pairing_complete = (aci_gap_pairing_complete_event_rp0*)blue_evt->data; if (pairing_complete->Status) { - FURI_LOG_E(GAP_TAG, "Pairing failed with status: %d. Terminating connection", pairing_complete->Status); + FURI_LOG_E(TAG, "Pairing failed with status: %d. Terminating connection", pairing_complete->Status); aci_gap_terminate(gap->gap_svc.connection_handle, 5); } else { - FURI_LOG_I(GAP_TAG, "Pairing complete"); + FURI_LOG_I(TAG, "Pairing complete"); BleEvent event = {.type = BleEventTypeConnected}; gap->on_event_cb(event, gap->context); } break; case EVT_BLUE_GAP_PROCEDURE_COMPLETE: - FURI_LOG_I(GAP_TAG, "Procedure complete event"); + FURI_LOG_I(TAG, "Procedure complete event"); break; } default: @@ -286,11 +286,11 @@ static void gap_init_svc(Gap* gap) { // Set GAP characteristics status = aci_gatt_update_char_value(gap->gap_svc.gap_svc_handle, gap->gap_svc.dev_name_char_handle, 0, strlen(name), (uint8_t *) name); if (status) { - FURI_LOG_E(GAP_TAG, "Failed updating name characteristic: %d", status); + FURI_LOG_E(TAG, "Failed updating name characteristic: %d", status); } status = aci_gatt_update_char_value(gap->gap_svc.gap_svc_handle, gap->gap_svc.appearance_char_handle, 0, 2, gap_appearence_char_uuid); if(status) { - FURI_LOG_E(GAP_TAG, "Failed updating appearence characteristic: %d", status); + FURI_LOG_E(TAG, "Failed updating appearence characteristic: %d", status); } // Set default PHY hci_le_set_default_phy(ALL_PHYS_PREFERENCE, TX_2M_PREFERRED, RX_2M_PREFERRED); @@ -322,7 +322,7 @@ static void gap_advertise_start(GapState new_state) // Stop advertising status = aci_gap_set_non_discoverable(); if (status) { - FURI_LOG_E(GAP_TAG, "Stop Advertising Failed, result: %d", status); + FURI_LOG_E(TAG, "Stop Advertising Failed, result: %d", status); } } // Configure advertising @@ -331,7 +331,7 @@ static void gap_advertise_start(GapState new_state) strlen(name), (uint8_t*)name, gap->gap_svc.adv_svc_uuid_len, gap->gap_svc.adv_svc_uuid, 0, 0); if(status) { - FURI_LOG_E(GAP_TAG, "Set discoverable err: %d", status); + FURI_LOG_E(TAG, "Set discoverable err: %d", status); } gap->state = new_state; BleEvent event = {.type = BleEventTypeStartAdvertising}; @@ -355,14 +355,14 @@ static void gap_advertise_stop() { } void gap_start_advertising() { - FURI_LOG_I(GAP_TAG, "Start advertising"); + FURI_LOG_I(TAG, "Start advertising"); gap->enable_adv = true; GapCommand command = GapCommandAdvFast; furi_check(osMessageQueuePut(gap->command_queue, &command, 0, 0) == osOK); } void gap_stop_advertising() { - FURI_LOG_I(GAP_TAG, "Stop advertising"); + FURI_LOG_I(TAG, "Stop advertising"); gap->enable_adv = false; GapCommand command = GapCommandAdvStop; furi_check(osMessageQueuePut(gap->command_queue, &command, 0, 0) == osOK); @@ -374,7 +374,7 @@ static void gap_advetise_timer_callback(void* context) { } bool gap_init(BleEventCallback on_event_cb, void* context) { - if (ble_glue_get_status() != BleGlueStatusStarted) { + if (!ble_glue_is_radio_stack_ready()) { return false; } @@ -393,7 +393,7 @@ bool gap_init(BleEventCallback on_event_cb, void* context) { gap->enable_adv = true; // Thread configuration - gap->thread_attr.name = "BLE advertising"; + gap->thread_attr.name = "BleGapWorker"; gap->thread_attr.stack_size = 1024; gap->thread_id = osThreadNew(gap_app, NULL, &gap->thread_attr); diff --git a/firmware/targets/f6/ble-glue/serial_service.c b/firmware/targets/f6/ble-glue/serial_service.c index 7de3529c..c7ea6db2 100644 --- a/firmware/targets/f6/ble-glue/serial_service.c +++ b/firmware/targets/f6/ble-glue/serial_service.c @@ -4,22 +4,27 @@ #include -#define SERIAL_SERVICE_TAG "serial service" +#define TAG "BtSerialSvc" typedef struct { uint16_t svc_handle; uint16_t rx_char_handle; uint16_t tx_char_handle; + uint16_t flow_ctrl_char_handle; + osMutexId_t buff_size_mtx; + uint32_t buff_size; + uint16_t bytes_ready_to_receive; SerialSvcDataReceivedCallback on_received_cb; SerialSvcDataSentCallback on_sent_cb; void* context; } SerialSvc; -static SerialSvc* serial_svc; +static SerialSvc* serial_svc = NULL; static const uint8_t service_uuid[] = {0x00, 0x00, 0xfe, 0x60, 0xcc, 0x7a, 0x48, 0x2a, 0x98, 0x4a, 0x7f, 0x2e, 0xd5, 0xb3, 0xe5, 0x8f}; -static const uint8_t char_rx_uuid[] = {0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; static const uint8_t char_tx_uuid[] = {0x00, 0x00, 0xfe, 0x61, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; +static const uint8_t char_rx_uuid[] = {0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; +static const uint8_t flow_ctrl_uuid[] = {0x00, 0x00, 0xfe, 0x63, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void *event) { SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck; @@ -32,16 +37,26 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void *event) { if(attribute_modified->Attr_Handle == serial_svc->rx_char_handle + 2) { // Descriptor handle ret = SVCCTL_EvtAckFlowEnable; - FURI_LOG_D(SERIAL_SERVICE_TAG, "RX descriptor event"); + FURI_LOG_D(TAG, "RX descriptor event"); } else if(attribute_modified->Attr_Handle == serial_svc->rx_char_handle + 1) { - FURI_LOG_D(SERIAL_SERVICE_TAG, "Received %d bytes", attribute_modified->Attr_Data_Length); + FURI_LOG_D(TAG, "Received %d bytes", attribute_modified->Attr_Data_Length); if(serial_svc->on_received_cb) { - serial_svc->on_received_cb(attribute_modified->Attr_Data, attribute_modified->Attr_Data_Length, serial_svc->context); + furi_check(osMutexAcquire(serial_svc->buff_size_mtx, osWaitForever) == osOK); + if(attribute_modified->Attr_Data_Length > serial_svc->bytes_ready_to_receive) { + FURI_LOG_W( + TAG, "Received %d, while was ready to receive %d bytes. Can lead to buffer overflow!", + attribute_modified->Attr_Data_Length, serial_svc->bytes_ready_to_receive); + } + serial_svc->bytes_ready_to_receive -= MIN(serial_svc->bytes_ready_to_receive, attribute_modified->Attr_Data_Length); + uint32_t buff_free_size = + serial_svc->on_received_cb(attribute_modified->Attr_Data, attribute_modified->Attr_Data_Length, serial_svc->context); + FURI_LOG_D(TAG, "Available buff size: %d", buff_free_size); + furi_check(osMutexRelease(serial_svc->buff_size_mtx) == osOK); } ret = SVCCTL_EvtAckFlowEnable; } } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) { - FURI_LOG_D(SERIAL_SERVICE_TAG, "Ack received", blecore_evt->ecode); + FURI_LOG_D(TAG, "Ack received", blecore_evt->ecode); if(serial_svc->on_sent_cb) { serial_svc->on_sent_cb(serial_svc->context); } @@ -58,9 +73,9 @@ void serial_svc_start() { SVCCTL_RegisterSvcHandler(serial_svc_event_handler); // Add service - status = aci_gatt_add_service(UUID_TYPE_128, (Service_UUID_t *)service_uuid, PRIMARY_SERVICE, 6, &serial_svc->svc_handle); + status = aci_gatt_add_service(UUID_TYPE_128, (Service_UUID_t *)service_uuid, PRIMARY_SERVICE, 10, &serial_svc->svc_handle); if(status) { - FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to add Serial service: %d", status); + FURI_LOG_E(TAG, "Failed to add Serial service: %d", status); } // Add RX characteristics @@ -73,12 +88,12 @@ void serial_svc_start() { CHAR_VALUE_LEN_VARIABLE, &serial_svc->rx_char_handle); if(status) { - FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to add RX characteristic: %d", status); + FURI_LOG_E(TAG, "Failed to add RX characteristic: %d", status); } // Add TX characteristic status = aci_gatt_add_char(serial_svc->svc_handle, UUID_TYPE_128, (const Char_UUID_t*)char_tx_uuid, - SERIAL_SVC_DATA_LEN_MAX, + SERIAL_SVC_DATA_LEN_MAX, CHAR_PROP_READ | CHAR_PROP_INDICATE, ATTR_PERMISSION_AUTHEN_READ, GATT_DONT_NOTIFY_EVENTS, @@ -86,14 +101,47 @@ void serial_svc_start() { CHAR_VALUE_LEN_VARIABLE, &serial_svc->tx_char_handle); if(status) { - FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to add TX characteristic: %d", status); + FURI_LOG_E(TAG, "Failed to add TX characteristic: %d", status); } + // Add Flow Control characteristic + status = aci_gatt_add_char(serial_svc->svc_handle, UUID_TYPE_128, (const Char_UUID_t*)flow_ctrl_uuid, + sizeof(uint32_t), + CHAR_PROP_READ | CHAR_PROP_NOTIFY, + ATTR_PERMISSION_AUTHEN_READ, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_CONSTANT, + &serial_svc->flow_ctrl_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add Flow Control characteristic: %d", status); + } + // Allocate buffer size mutex + serial_svc->buff_size_mtx = osMutexNew(NULL); } -void serial_svc_set_callbacks(SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context) { +void serial_svc_set_callbacks(uint16_t buff_size, SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context) { + furi_assert(serial_svc); serial_svc->on_received_cb = on_received_cb; serial_svc->on_sent_cb = on_sent_cb; serial_svc->context = context; + serial_svc->buff_size = buff_size; + serial_svc->bytes_ready_to_receive = buff_size; + uint32_t buff_size_reversed = REVERSE_BYTES_U32(serial_svc->buff_size); + aci_gatt_update_char_value(serial_svc->svc_handle, serial_svc->flow_ctrl_char_handle, 0, sizeof(uint32_t), (uint8_t*)&buff_size_reversed); +} + +void serial_svc_notify_buffer_is_empty() { + furi_assert(serial_svc); + furi_assert(serial_svc->buff_size_mtx); + + furi_check(osMutexAcquire(serial_svc->buff_size_mtx, osWaitForever) == osOK); + if(serial_svc->bytes_ready_to_receive == 0) { + FURI_LOG_D(TAG, "Buffer is empty. Notifying client"); + serial_svc->bytes_ready_to_receive = serial_svc->buff_size; + uint32_t buff_size_reversed = REVERSE_BYTES_U32(serial_svc->buff_size); + aci_gatt_update_char_value(serial_svc->svc_handle, serial_svc->flow_ctrl_char_handle, 0, sizeof(uint32_t), (uint8_t*)&buff_size_reversed); + } + furi_check(osMutexRelease(serial_svc->buff_size_mtx) == osOK); } void serial_svc_stop() { @@ -102,17 +150,23 @@ void serial_svc_stop() { // Delete characteristics status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->tx_char_handle); if(status) { - FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to delete TX characteristic: %d", status); + FURI_LOG_E(TAG, "Failed to delete TX characteristic: %d", status); } status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->rx_char_handle); if(status) { - FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to delete RX characteristic: %d", status); + FURI_LOG_E(TAG, "Failed to delete RX characteristic: %d", status); + } + status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->flow_ctrl_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete Flow Control characteristic: %d", status); } // Delete service status = aci_gatt_del_service(serial_svc->svc_handle); if(status) { - FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to delete Serial service: %d", status); + FURI_LOG_E(TAG, "Failed to delete Serial service: %d", status); } + // Delete buffer size mutex + osMutexDelete(serial_svc->buff_size_mtx); free(serial_svc); serial_svc = NULL; } @@ -122,14 +176,13 @@ bool serial_svc_update_tx(uint8_t* data, uint8_t data_len) { if(data_len > SERIAL_SVC_DATA_LEN_MAX) { return false; } - FURI_LOG_D(SERIAL_SERVICE_TAG, "Updating char %d len", data_len); tBleStatus result = aci_gatt_update_char_value(serial_svc->svc_handle, serial_svc->tx_char_handle, 0, data_len, data); if(result) { - FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed updating TX characteristic: %d", result); + FURI_LOG_E(TAG, "Failed updating TX characteristic: %d", result); } return result != BLE_STATUS_SUCCESS; } diff --git a/firmware/targets/f6/ble-glue/serial_service.h b/firmware/targets/f6/ble-glue/serial_service.h index b5a1c078..0aa4c79f 100644 --- a/firmware/targets/f6/ble-glue/serial_service.h +++ b/firmware/targets/f6/ble-glue/serial_service.h @@ -9,12 +9,14 @@ extern "C" { #endif -typedef void(*SerialSvcDataReceivedCallback)(uint8_t* buff, uint16_t size, void* context); +typedef uint16_t(*SerialSvcDataReceivedCallback)(uint8_t* buff, uint16_t size, void* context); typedef void(*SerialSvcDataSentCallback)(void* context); void serial_svc_start(); -void serial_svc_set_callbacks(SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context); +void serial_svc_set_callbacks(uint16_t buff_size, SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context); + +void serial_svc_notify_buffer_is_empty(); void serial_svc_stop(); diff --git a/firmware/targets/f6/Src/fatfs/fatfs.c b/firmware/targets/f6/fatfs/fatfs.c similarity index 100% rename from firmware/targets/f6/Src/fatfs/fatfs.c rename to firmware/targets/f6/fatfs/fatfs.c diff --git a/firmware/targets/f6/Src/fatfs/fatfs.h b/firmware/targets/f6/fatfs/fatfs.h similarity index 100% rename from firmware/targets/f6/Src/fatfs/fatfs.h rename to firmware/targets/f6/fatfs/fatfs.h diff --git a/firmware/targets/f6/Src/fatfs/ffconf.h b/firmware/targets/f6/fatfs/ffconf.h similarity index 100% rename from firmware/targets/f6/Src/fatfs/ffconf.h rename to firmware/targets/f6/fatfs/ffconf.h diff --git a/firmware/targets/f6/Src/fatfs/spi_sd_hal.c b/firmware/targets/f6/fatfs/spi_sd_hal.c similarity index 100% rename from firmware/targets/f6/Src/fatfs/spi_sd_hal.c rename to firmware/targets/f6/fatfs/spi_sd_hal.c diff --git a/firmware/targets/f6/Src/fatfs/stm32_adafruit_sd.c b/firmware/targets/f6/fatfs/stm32_adafruit_sd.c similarity index 100% rename from firmware/targets/f6/Src/fatfs/stm32_adafruit_sd.c rename to firmware/targets/f6/fatfs/stm32_adafruit_sd.c diff --git a/firmware/targets/f6/Src/fatfs/stm32_adafruit_sd.h b/firmware/targets/f6/fatfs/stm32_adafruit_sd.h similarity index 100% rename from firmware/targets/f6/Src/fatfs/stm32_adafruit_sd.h rename to firmware/targets/f6/fatfs/stm32_adafruit_sd.h diff --git a/firmware/targets/f6/Src/fatfs/syscall.c b/firmware/targets/f6/fatfs/syscall.c similarity index 100% rename from firmware/targets/f6/Src/fatfs/syscall.c rename to firmware/targets/f6/fatfs/syscall.c diff --git a/firmware/targets/f6/Src/fatfs/user_diskio.c b/firmware/targets/f6/fatfs/user_diskio.c similarity index 100% rename from firmware/targets/f6/Src/fatfs/user_diskio.c rename to firmware/targets/f6/fatfs/user_diskio.c diff --git a/firmware/targets/f6/Src/fatfs/user_diskio.h b/firmware/targets/f6/fatfs/user_diskio.h similarity index 100% rename from firmware/targets/f6/Src/fatfs/user_diskio.h rename to firmware/targets/f6/fatfs/user_diskio.h diff --git a/firmware/targets/f6/furi-hal/furi-hal-bootloader.c b/firmware/targets/f6/furi-hal/furi-hal-bootloader.c index 2962877e..e8ea913e 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-bootloader.c +++ b/firmware/targets/f6/furi-hal/furi-hal-bootloader.c @@ -2,6 +2,8 @@ #include #include +#define TAG "FuriHalBoot" + // Boot request enum #define BOOT_REQUEST_TAINTED 0x00000000 #define BOOT_REQUEST_CLEAN 0xDADEDADE @@ -11,7 +13,7 @@ void furi_hal_bootloader_init() { #ifndef DEBUG LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_TAINTED); #endif - FURI_LOG_I("FuriHalBoot", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_bootloader_set_mode(FuriHalBootloaderMode mode) { diff --git a/firmware/targets/f6/furi-hal/furi-hal-bt.c b/firmware/targets/f6/furi-hal/furi-hal-bt.c index a018085c..b74a9e29 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-bt.c +++ b/firmware/targets/f6/furi-hal/furi-hal-bt.c @@ -6,36 +6,41 @@ #include +#define TAG "FuriHalBt" + osMutexId_t furi_hal_bt_core2_mtx = NULL; void furi_hal_bt_init() { furi_hal_bt_core2_mtx = osMutexNew(NULL); + furi_assert(furi_hal_bt_core2_mtx); + + // Explicitly tell that we are in charge of CLK48 domain + HAL_HSEM_FastTake(CFG_HW_CLK48_CONFIG_SEMID); + + // Start Core2 + ble_glue_init(); } -static bool furi_hal_bt_wait_startup() { - uint16_t counter = 0; - while (!(ble_glue_get_status() == BleGlueStatusStarted || ble_glue_get_status() == BleGlueStatusBleStackMissing)) { - osDelay(10); - counter++; - if (counter > 1000) { - return false; - } - } - return true; +void furi_hal_bt_lock_core2() { + furi_assert(furi_hal_bt_core2_mtx); + furi_check(osMutexAcquire(furi_hal_bt_core2_mtx, osWaitForever) == osOK); +} + +void furi_hal_bt_unlock_core2() { + furi_assert(furi_hal_bt_core2_mtx); + furi_check(osMutexRelease(furi_hal_bt_core2_mtx) == osOK); } bool furi_hal_bt_start_core2() { furi_assert(furi_hal_bt_core2_mtx); - bool ret = false; osMutexAcquire(furi_hal_bt_core2_mtx, osWaitForever); // Explicitly tell that we are in charge of CLK48 domain HAL_HSEM_FastTake(CFG_HW_CLK48_CONFIG_SEMID); // Start Core2 - ble_glue_init(); - // Wait for Core2 start - ret = furi_hal_bt_wait_startup(); + bool ret = ble_glue_start(); osMutexRelease(furi_hal_bt_core2_mtx); + return ret; } @@ -59,8 +64,12 @@ void furi_hal_bt_stop_advertising() { } } -void furi_hal_bt_set_data_event_callbacks(SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context) { - serial_svc_set_callbacks(on_received_cb, on_sent_cb, context); +void furi_hal_bt_set_data_event_callbacks(uint16_t buff_size, SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context) { + serial_svc_set_callbacks(buff_size, on_received_cb, on_sent_cb, context); +} + +void furi_hal_bt_notify_buffer_is_empty() { + serial_svc_notify_buffer_is_empty(); } bool furi_hal_bt_tx(uint8_t* data, uint16_t size) { @@ -70,14 +79,8 @@ bool furi_hal_bt_tx(uint8_t* data, uint16_t size) { return serial_svc_update_tx(data, size); } -bool furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size) { - bool ret = false; - BleGlueStatus status = ble_glue_get_status(); - if(status == BleGlueStatusUninitialized || BleGlueStatusStarted) { - ble_app_get_key_storage_buff(key_buff_addr, key_buff_size); - ret = true; - } - return ret; +void furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size) { + ble_app_get_key_storage_buff(key_buff_addr, key_buff_size); } void furi_hal_bt_set_key_storage_change_callback(BleGlueKeyStorageChangedCallback callback, void* context) { @@ -96,8 +99,7 @@ void furi_hal_bt_nvm_sram_sem_release() { } void furi_hal_bt_dump_state(string_t buffer) { - BleGlueStatus status = ble_glue_get_status(); - if (status == BleGlueStatusStarted) { + if (furi_hal_bt_is_alive()) { uint8_t HCI_Version; uint16_t HCI_Revision; uint8_t LMP_PAL_Version; @@ -118,99 +120,13 @@ void furi_hal_bt_dump_state(string_t buffer) { } bool furi_hal_bt_is_alive() { - BleGlueStatus status = ble_glue_get_status(); - return (status == BleGlueStatusBleStackMissing) || (status == BleGlueStatusStarted); + return ble_glue_is_alive(); } bool furi_hal_bt_is_active() { return gap_get_state() > GapStateIdle; } -static void furi_hal_bt_lock_flash_core2(bool erase_flag) { - // Take flash controller ownership - while (HAL_HSEM_FastTake(CFG_HW_FLASH_SEMID) != HAL_OK) { - taskYIELD(); - } - - // Unlock flash operation - HAL_FLASH_Unlock(); - - // Erase activity notification - if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON); - - while(true) { - // Wait till flash controller become usable - while(LL_FLASH_IsActiveFlag_OperationSuspended()) { - taskYIELD(); - }; - - // Just a little more love - taskENTER_CRITICAL(); - - // Actually we already have mutex for it, but specification is specification - if (HAL_HSEM_IsSemTaken(CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID)) { - taskEXIT_CRITICAL(); - continue; - } - - // Take sempahopre and prevent core2 from anyting funky - if (HAL_HSEM_FastTake(CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID) != HAL_OK) { - taskEXIT_CRITICAL(); - continue; - } - - break; - } -} - -void furi_hal_bt_lock_flash(bool erase_flag) { - // Acquire dangerous ops mutex - osMutexAcquire(furi_hal_bt_core2_mtx, osWaitForever); - - // If Core2 is running use IPC locking - BleGlueStatus status = ble_glue_get_status(); - if(status == BleGlueStatusStarted || status == BleGlueStatusBleStackMissing) { - furi_hal_bt_lock_flash_core2(erase_flag); - } else { - HAL_FLASH_Unlock(); - } -} - -static void furi_hal_bt_unlock_flash_core2(bool erase_flag) { - // Funky ops are ok at this point - HAL_HSEM_Release(CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID, 0); - - // Task switching is ok - taskEXIT_CRITICAL(); - - // Doesn't make much sense, does it? - while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { - taskYIELD(); - } - - // Erase activity over, core2 can continue - if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF); - - // Lock flash controller - HAL_FLASH_Lock(); - - // Release flash controller ownership - HAL_HSEM_Release(CFG_HW_FLASH_SEMID, 0); -} - -void furi_hal_bt_unlock_flash(bool erase_flag) { - // If Core2 is running use IPC locking - BleGlueStatus status = ble_glue_get_status(); - if(status == BleGlueStatusStarted || status == BleGlueStatusBleStackMissing) { - furi_hal_bt_unlock_flash_core2(erase_flag); - } else { - HAL_FLASH_Lock(); - } - - // Release dangerous ops mutex - osMutexRelease(furi_hal_bt_core2_mtx); -} - void furi_hal_bt_start_tone_tx(uint8_t channel, uint8_t power) { aci_hal_set_tx_power_level(0, power); aci_hal_tone_start(channel, 0); diff --git a/firmware/targets/f6/furi-hal/furi-hal-clock.c b/firmware/targets/f6/furi-hal/furi-hal-clock.c index fd4899d4..7a124049 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-clock.c +++ b/firmware/targets/f6/furi-hal/furi-hal-clock.c @@ -5,6 +5,8 @@ #include #include +#define TAG "FuriHalClock" + #define HS_CLOCK_IS_READY() (LL_RCC_HSE_IsReady() && LL_RCC_HSI_IsReady()) #define LS_CLOCK_IS_READY() (LL_RCC_LSE_IsReady() && LL_RCC_LSI1_IsReady()) @@ -123,7 +125,7 @@ void furi_hal_clock_init() { // APB2 LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1); - FURI_LOG_I("FuriHalClock", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_clock_switch_to_hsi() { diff --git a/firmware/targets/f6/furi-hal/furi-hal-compress.c b/firmware/targets/f6/furi-hal/furi-hal-compress.c index 9b7678f5..eb6e9d51 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-compress.c +++ b/firmware/targets/f6/furi-hal/furi-hal-compress.c @@ -4,6 +4,8 @@ #include #include +#define TAG "FuriHalCompress" + #define FURI_HAL_COMPRESS_ICON_ENCODED_BUFF_SIZE (512) #define FURI_HAL_COMPRESS_ICON_DECODED_BUFF_SIZE (1024) @@ -46,7 +48,7 @@ void furi_hal_compress_icon_init() { FURI_HAL_COMPRESS_LOOKAHEAD_BUFF_SIZE_LOG); heatshrink_decoder_reset(icon_decoder->decoder); memset(icon_decoder->decoded_buff, 0, sizeof(icon_decoder->decoded_buff)); - FURI_LOG_I("FuriHalCompress", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_compress_icon_decode(const uint8_t* icon_data, uint8_t** decoded_buff) { diff --git a/firmware/targets/f6/furi-hal/furi-hal-console.c b/firmware/targets/f6/furi-hal/furi-hal-console.c index ffe340b9..993b498e 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-console.c +++ b/firmware/targets/f6/furi-hal/furi-hal-console.c @@ -6,8 +6,12 @@ #include #include +#include + #include +#define TAG "FuriHalConsole" + #define CONSOLE_BAUDRATE 230400 volatile bool furi_hal_console_alive = false; @@ -16,7 +20,7 @@ void furi_hal_console_init() { furi_hal_uart_init(FuriHalUartIdUSART1, CONSOLE_BAUDRATE); furi_hal_console_alive = true; - FURI_LOG_I("FuriHalConsole", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_console_enable() { @@ -35,22 +39,26 @@ void furi_hal_console_tx(const uint8_t* buffer, size_t buffer_size) { if (!furi_hal_console_alive) return; + UTILS_ENTER_CRITICAL_SECTION(); // Transmit data furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)buffer, buffer_size); // Wait for TC flag to be raised for last char while (!LL_USART_IsActiveFlag_TC(USART1)); + UTILS_EXIT_CRITICAL_SECTION(); } void furi_hal_console_tx_with_new_line(const uint8_t* buffer, size_t buffer_size) { if (!furi_hal_console_alive) return; + UTILS_ENTER_CRITICAL_SECTION(); // Transmit data furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)buffer, buffer_size); // Transmit new line symbols furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)"\r\n", 2); // Wait for TC flag to be raised for last char while (!LL_USART_IsActiveFlag_TC(USART1)); + UTILS_EXIT_CRITICAL_SECTION(); } void furi_hal_console_printf(const char format[], ...) { diff --git a/firmware/targets/f6/furi-hal/furi-hal-crypto.c b/firmware/targets/f6/furi-hal/furi-hal-crypto.c index 648f3f18..91875d23 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-crypto.c +++ b/firmware/targets/f6/furi-hal/furi-hal-crypto.c @@ -3,10 +3,12 @@ #include #include +#define TAG "FuriHalCrypto" + CRYP_HandleTypeDef crypt; void furi_hal_crypto_init() { - FURI_LOG_I("FuriHalCrypto", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } bool furi_hal_crypto_store_add_key(FuriHalCryptoKey* key, uint8_t* slot) { diff --git a/firmware/targets/f6/furi-hal/furi-hal-delay.c b/firmware/targets/f6/furi-hal/furi-hal-delay.c index 52de8715..b5f3c334 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-delay.c +++ b/firmware/targets/f6/furi-hal/furi-hal-delay.c @@ -3,6 +3,8 @@ #include #include +#define TAG "FuriHalDelay" + static uint32_t clk_per_microsecond; void furi_hal_delay_init(void) { @@ -10,7 +12,7 @@ void furi_hal_delay_init(void) { DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; DWT->CYCCNT = 0U; clk_per_microsecond = SystemCoreClock / 1000000.0f; - FURI_LOG_I("FuriHalDelay", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void delay_us(float microseconds) { diff --git a/firmware/targets/f6/furi-hal/furi-hal-flash.c b/firmware/targets/f6/furi-hal/furi-hal-flash.c index 1e270bc0..156a26a9 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-flash.c +++ b/firmware/targets/f6/furi-hal/furi-hal-flash.c @@ -1,12 +1,11 @@ #include #include #include +#include +#include #include -/* Free flash space borders, exported by linker */ -extern const void __free_flash_start__; - #define FURI_HAL_TAG "FuriHalFlash" #define FURI_HAL_CRITICAL_MSG "Critical flash operation fail" #define FURI_HAL_FLASH_READ_BLOCK 8 @@ -14,6 +13,9 @@ extern const void __free_flash_start__; #define FURI_HAL_FLASH_PAGE_SIZE 4096 #define FURI_HAL_FLASH_CYCLES_COUNT 10000 +/* Free flash space borders, exported by linker */ +extern const void __free_flash_start__; + size_t furi_hal_flash_get_base() { return FLASH_BASE; } @@ -39,9 +41,9 @@ const void* furi_hal_flash_get_free_start_address() { } const void* furi_hal_flash_get_free_end_address() { - FLASH_OBProgramInitTypeDef pOBInit; - HAL_FLASHEx_OBGetConfig(&pOBInit); - return (const void *)pOBInit.SecureFlashStartAddr; + uint32_t sfr_reg_val = READ_REG(FLASH->SFR); + uint32_t sfsa = (READ_BIT(sfr_reg_val, FLASH_SFR_SFSA) >> FLASH_SFR_SFSA_Pos); + return (const void *)((sfsa * FLASH_PAGE_SIZE) + FLASH_BASE); } size_t furi_hal_flash_get_free_page_start_address() { @@ -59,47 +61,239 @@ size_t furi_hal_flash_get_free_page_count() { return (end-page_start) / FURI_HAL_FLASH_PAGE_SIZE; } -bool furi_hal_flash_erase(uint8_t page, uint8_t count) { - furi_hal_bt_lock_flash(true); +static void furi_hal_flash_unlock() { + /* verify Flash is locked */ + furi_check(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U); - FLASH_EraseInitTypeDef erase; - erase.TypeErase = FLASH_TYPEERASE_PAGES; - erase.Page = page; - erase.NbPages = count; + /* Authorize the FLASH Registers access */ + WRITE_REG(FLASH->KEYR, FLASH_KEY1); + WRITE_REG(FLASH->KEYR, FLASH_KEY2); - uint32_t error_page = 0; - HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase, &error_page); - if (status != HAL_OK) { - FURI_LOG_E(FURI_HAL_TAG, "Erase failed, ret: %d, page: %d", status, error_page); - furi_crash(FURI_HAL_CRITICAL_MSG); + /* verify Flash is unlock */ + furi_check(READ_BIT(FLASH->CR, FLASH_CR_LOCK) == 0U); +} + +static void furi_hal_flash_lock(void) { + /* verify Flash is unlocked */ + furi_check(READ_BIT(FLASH->CR, FLASH_CR_LOCK) == 0U); + + /* Set the LOCK Bit to lock the FLASH Registers access */ + /* @Note The lock and unlock procedure is done only using CR registers even from CPU2 */ + SET_BIT(FLASH->CR, FLASH_CR_LOCK); + + /* verify Flash is locked */ + furi_check(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U); +} + +static void furi_hal_flash_begin_with_core2(bool erase_flag) { + // Take flash controller ownership + while (HAL_HSEM_FastTake(CFG_HW_FLASH_SEMID) != HAL_OK) { + taskYIELD(); } - furi_hal_bt_unlock_flash(true); + // Unlock flash operation + furi_hal_flash_unlock(); + + // Erase activity notification + if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON); + + while(true) { + // Wait till flash controller become usable + while(LL_FLASH_IsActiveFlag_OperationSuspended()) { + taskYIELD(); + }; + + // Just a little more love + taskENTER_CRITICAL(); + + // Actually we already have mutex for it, but specification is specification + if (HAL_HSEM_IsSemTaken(CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID)) { + taskEXIT_CRITICAL(); + continue; + } + + // Take sempahopre and prevent core2 from anyting funky + if (HAL_HSEM_FastTake(CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID) != HAL_OK) { + taskEXIT_CRITICAL(); + continue; + } + + break; + } +} + +static void furi_hal_flash_begin(bool erase_flag) { + // Acquire dangerous ops mutex + furi_hal_bt_lock_core2(); + + // If Core2 is running use IPC locking + if(furi_hal_bt_is_alive()) { + furi_hal_flash_begin_with_core2(erase_flag); + } else { + furi_hal_flash_unlock(); + } +} + +static void furi_hal_flash_end_with_core2(bool erase_flag) { + // Funky ops are ok at this point + HAL_HSEM_Release(CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID, 0); + + // Task switching is ok + taskEXIT_CRITICAL(); + + // Doesn't make much sense, does it? + while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + taskYIELD(); + } + + // Erase activity over, core2 can continue + if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF); + + // Lock flash controller + furi_hal_flash_lock(); + + // Release flash controller ownership + HAL_HSEM_Release(CFG_HW_FLASH_SEMID, 0); +} + +static void furi_hal_flash_end(bool erase_flag) { + // If Core2 is running use IPC locking + if(furi_hal_bt_is_alive()) { + furi_hal_flash_end_with_core2(erase_flag); + } else { + furi_hal_flash_lock(); + } + + // Release dangerous ops mutex + furi_hal_bt_unlock_core2(); +} + +static void furi_hal_flush_cache(void) { + /* Flush instruction cache */ + if (READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) == FLASH_ACR_ICEN) { + /* Disable instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); + /* Reset instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_RESET(); + /* Enable instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_ENABLE(); + } + + /* Flush data cache */ + if (READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) == FLASH_ACR_DCEN) { + /* Disable data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + /* Reset data cache */ + __HAL_FLASH_DATA_CACHE_RESET(); + /* Enable data cache */ + __HAL_FLASH_DATA_CACHE_ENABLE(); + } +} + +HAL_StatusTypeDef furi_hal_flash_wait_last_operation(uint32_t timeout) { + uint32_t error = 0; + uint32_t countdown = 0; + + // Wait for the FLASH operation to complete by polling on BUSY flag to be reset. + // Even if the FLASH operation fails, the BUSY flag will be reset and an error + // flag will be set + countdown = timeout; + while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + if(LL_SYSTICK_IsActiveCounterFlag()) { + countdown--; + } + if (countdown == 0) { + return HAL_TIMEOUT; + } + } + + /* Check FLASH operation error flags */ + error = FLASH->SR; + + /* Check FLASH End of Operation flag */ + if ((error & FLASH_FLAG_EOP) != 0U) { + /* Clear FLASH End of Operation pending bit */ + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); + } + + /* Now update error variable to only error value */ + error &= FLASH_FLAG_SR_ERRORS; + + furi_check(error == 0); + + /* clear error flags */ + __HAL_FLASH_CLEAR_FLAG(error); + + /* Wait for control register to be written */ + countdown = timeout; + while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY)) { + if(LL_SYSTICK_IsActiveCounterFlag()) { + countdown--; + } + if (countdown == 0) { + return HAL_TIMEOUT; + } + } + + return HAL_OK; +} + +bool furi_hal_flash_erase(uint8_t page) { + furi_hal_flash_begin(true); + + // Ensure that controller state is valid + furi_check(FLASH->SR == 0); + + /* Verify that next operation can be proceed */ + furi_check(furi_hal_flash_wait_last_operation(FLASH_TIMEOUT_VALUE) == HAL_OK); + + /* Select page and start operation */ + MODIFY_REG(FLASH->CR, FLASH_CR_PNB, ((page << FLASH_CR_PNB_Pos) | FLASH_CR_PER | FLASH_CR_STRT)); + + /* Wait for last operation to be completed */ + furi_check(furi_hal_flash_wait_last_operation(FLASH_TIMEOUT_VALUE) == HAL_OK); + + /* If operation is completed or interrupted, disable the Page Erase Bit */ + CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB)); + + /* Flush the caches to be sure of the data consistency */ + furi_hal_flush_cache(); + + furi_hal_flash_end(true); return true; } bool furi_hal_flash_write_dword(size_t address, uint64_t data) { - furi_hal_bt_lock_flash(false); + furi_hal_flash_begin(false); - HAL_StatusTypeDef status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data); - if (status != HAL_OK) { - FURI_LOG_E(FURI_HAL_TAG, "Programming failed, ret: %d, address: %p", status, address); - furi_crash(FURI_HAL_CRITICAL_MSG); - } + // Ensure that controller state is valid + furi_check(FLASH->SR == 0); - furi_hal_bt_unlock_flash(false); - - return true; -} - -bool furi_hal_flash_write_row(size_t address, size_t source_address) { - furi_hal_bt_lock_flash(false); - - HAL_StatusTypeDef status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST, address, source_address); - furi_check(status == HAL_OK); - - furi_hal_bt_unlock_flash(false); + /* Check the parameters */ + furi_check(IS_ADDR_ALIGNED_64BITS(address)); + furi_check(IS_FLASH_PROGRAM_ADDRESS(address)); + + /* Set PG bit */ + SET_BIT(FLASH->CR, FLASH_CR_PG); + + /* Program first word */ + *(uint32_t *)address = (uint32_t)data; + + // Barrier to ensure programming is performed in 2 steps, in right order + // (independently of compiler optimization behavior) + __ISB(); + + /* Program second word */ + *(uint32_t *)(address + 4U) = (uint32_t)(data >> 32U); + + /* Wait for last operation to be completed */ + furi_check(furi_hal_flash_wait_last_operation(FLASH_TIMEOUT_VALUE) == HAL_OK); + + /* If the program operation is completed, disable the PG or FSTPG Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_PG); + + furi_hal_flash_end(false); return true; } diff --git a/firmware/targets/f6/furi-hal/furi-hal-flash.h b/firmware/targets/f6/furi-hal/furi-hal-flash.h index 92a65a65..3d8031e6 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-flash.h +++ b/firmware/targets/f6/furi-hal/furi-hal-flash.h @@ -60,18 +60,17 @@ size_t furi_hal_flash_get_free_page_count(); /** Erase Flash * - * Locking operation, uses HSEM to manage shared access. + * @warning locking operation with critical section, stales execution * - * @param page page number - * @param count page count to erase + * @param page The page to erase * * @return true on success */ -bool furi_hal_flash_erase(uint8_t page, uint8_t count); +bool furi_hal_flash_erase(uint8_t page); /** Write double word (64 bits) * - * Locking operation, uses HSEM to manage shared access. + * @warning locking operation with critical section, stales execution * * @param address destination address, must be double word aligned. * @param data data to write @@ -80,13 +79,3 @@ bool furi_hal_flash_erase(uint8_t page, uint8_t count); */ bool furi_hal_flash_write_dword(size_t address, uint64_t data); -/** Write row: 64 double word (64 bits) from address - * - * Locking operation, uses HSEM to manage shared access. - * - * @param address destination address, must be block aligned - * @param source_address source address - * - * @return true on success - */ -bool furi_hal_flash_write_row(size_t address, size_t source_address); diff --git a/firmware/targets/f6/furi-hal/furi-hal-i2c.c b/firmware/targets/f6/furi-hal/furi-hal-i2c.c index 196a2a7b..b1ec4711 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-i2c.c +++ b/firmware/targets/f6/furi-hal/furi-hal-i2c.c @@ -6,6 +6,8 @@ #include #include +#define TAG "FuriHalI2C" + osMutexId_t furi_hal_i2c_mutex = NULL; void furi_hal_i2c_init() { @@ -42,7 +44,7 @@ void furi_hal_i2c_init() { LL_I2C_DisableOwnAddress2(POWER_I2C); LL_I2C_DisableGeneralCall(POWER_I2C); LL_I2C_EnableClockStretching(POWER_I2C); - FURI_LOG_I("FuriHalI2C", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } bool furi_hal_i2c_tx( diff --git a/firmware/targets/f6/furi-hal/furi-hal-interrupt.c b/firmware/targets/f6/furi-hal/furi-hal-interrupt.c index 47e99c9f..2685edab 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-interrupt.c +++ b/firmware/targets/f6/furi-hal/furi-hal-interrupt.c @@ -4,6 +4,8 @@ #include #include +#define TAG "FuriHalInterrupt" + volatile FuriHalInterruptISR furi_hal_tim_tim2_isr = NULL; volatile FuriHalInterruptISR furi_hal_tim_tim1_isr = NULL; @@ -22,7 +24,7 @@ void furi_hal_interrupt_init() { NVIC_SetPriority(DMA1_Channel1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); NVIC_EnableIRQ(DMA1_Channel1_IRQn); - FURI_LOG_I("FuriHalInterrupt", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_interrupt_set_timer_isr(TIM_TypeDef* timer, FuriHalInterruptISR isr) { @@ -161,10 +163,10 @@ void TAMP_STAMP_LSECSS_IRQHandler(void) { if (LL_RCC_IsActiveFlag_LSECSS()) { LL_RCC_ClearFlag_LSECSS(); if (!LL_RCC_LSE_IsReady()) { - FURI_LOG_E("FuriHalInterrupt", "LSE CSS fired: resetting system"); + FURI_LOG_E(TAG, "LSE CSS fired: resetting system"); NVIC_SystemReset(); } else { - FURI_LOG_E("FuriHalInterrupt", "LSE CSS fired: but LSE is alive"); + FURI_LOG_E(TAG, "LSE CSS fired: but LSE is alive"); } } } @@ -176,7 +178,7 @@ void RCC_IRQHandler(void) { void NMI_Handler(void) { if (LL_RCC_IsActiveFlag_HSECSS()) { LL_RCC_ClearFlag_HSECSS(); - FURI_LOG_E("FuriHalInterrupt", "HSE CSS fired: resetting system"); + FURI_LOG_E(TAG, "HSE CSS fired: resetting system"); NVIC_SystemReset(); } } diff --git a/firmware/targets/f6/furi-hal/furi-hal-light.c b/firmware/targets/f6/furi-hal/furi-hal-light.c index fba1bec4..ecf0d4f2 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-light.c +++ b/firmware/targets/f6/furi-hal/furi-hal-light.c @@ -1,6 +1,8 @@ #include #include +#define TAG "FuriHalLight" + #define LED_CURRENT_RED 50 #define LED_CURRENT_GREEN 50 #define LED_CURRENT_BLUE 50 @@ -21,7 +23,7 @@ void furi_hal_light_init() { lp5562_enable(); lp5562_configure(); - FURI_LOG_I("FuriHalLight", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_light_set(Light light, uint8_t value) { diff --git a/firmware/targets/f6/furi-hal/furi-hal-nfc.c b/firmware/targets/f6/furi-hal/furi-hal-nfc.c index d92e2cad..4bca12a9 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-nfc.c +++ b/firmware/targets/f6/furi-hal/furi-hal-nfc.c @@ -1,15 +1,17 @@ #include "furi-hal-nfc.h" #include +#define TAG "FuriHalNfc" + static const uint32_t clocks_in_ms = 64 * 1000; void furi_hal_nfc_init() { ReturnCode ret = rfalNfcInitialize(); if(ret == ERR_NONE) { furi_hal_nfc_start_sleep(); - FURI_LOG_I("FuriHalNfc", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } else { - FURI_LOG_W("FuriHalNfc", "Initialization failed, RFAL returned: %d", ret); + FURI_LOG_W(TAG, "Initialization failed, RFAL returned: %d", ret); } } @@ -63,7 +65,7 @@ bool furi_hal_nfc_detect(rfalNfcDevice **dev_list, uint8_t* dev_cnt, uint32_t ti while(state != RFAL_NFC_STATE_ACTIVATED) { rfalNfcWorker(); state = rfalNfcGetState(); - FURI_LOG_D("HAL NFC", "Current state %d", state); + FURI_LOG_D(TAG, "Current state %d", state); if(state == RFAL_NFC_STATE_POLL_ACTIVATION) { start = DWT->CYCCNT; continue; @@ -73,7 +75,7 @@ bool furi_hal_nfc_detect(rfalNfcDevice **dev_list, uint8_t* dev_cnt, uint32_t ti } if(DWT->CYCCNT - start > timeout * clocks_in_ms) { rfalNfcDeactivate(true); - FURI_LOG_D("HAL NFC", "Timeout"); + FURI_LOG_D(TAG, "Timeout"); return false; } osThreadYield(); diff --git a/firmware/targets/f6/furi-hal/furi-hal-os.c b/firmware/targets/f6/furi-hal/furi-hal-os.c index eb1811b6..aac1b10e 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-os.c +++ b/firmware/targets/f6/furi-hal/furi-hal-os.c @@ -5,6 +5,8 @@ #include +#define TAG "FuriHalOs" + #define FURI_HAL_OS_CLK_FREQUENCY 32768 #define FURI_HAL_OS_TICK_PER_SECOND 1024 #define FURI_HAL_OS_CLK_PER_TICK (FURI_HAL_OS_CLK_FREQUENCY / FURI_HAL_OS_TICK_PER_SECOND) @@ -44,7 +46,7 @@ void furi_hal_os_init() { osTimerStart(second_timer, 1024); #endif - FURI_LOG_I("FuriHalOs", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void LPTIM2_IRQHandler(void) { diff --git a/firmware/targets/f6/furi-hal/furi-hal-power.c b/firmware/targets/f6/furi-hal/furi-hal-power.c index 47ce5f4d..870cbda6 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-power.c +++ b/firmware/targets/f6/furi-hal/furi-hal-power.c @@ -15,6 +15,8 @@ #include +#define TAG "FuriHalPower" + typedef struct { volatile uint8_t insomnia; volatile uint8_t deep_insomnia; @@ -74,7 +76,7 @@ void furi_hal_power_init() { LL_PWR_SMPS_SetMode(LL_PWR_SMPS_STEP_DOWN); bq27220_init(&cedv); bq25896_init(); - FURI_LOG_I("FuriHalPower", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } uint16_t furi_hal_power_insomnia_level() { diff --git a/firmware/targets/f6/furi-hal/furi-hal-rfid.c b/firmware/targets/f6/furi-hal/furi-hal-rfid.c index a9bbc32c..d7092f88 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-rfid.c +++ b/firmware/targets/f6/furi-hal/furi-hal-rfid.c @@ -104,7 +104,7 @@ void furi_hal_rfid_tim_read(float freq, float duty_cycle) { sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; - if(HAL_TIM_OC_ConfigChannel(&LFRFID_READ_TIM, &sConfigOC, LFRFID_READ_CHANNEL) != HAL_OK) { + if(HAL_TIM_PWM_ConfigChannel(&LFRFID_READ_TIM, &sConfigOC, LFRFID_READ_CHANNEL) != HAL_OK) { Error_Handler(); } @@ -142,7 +142,6 @@ void furi_hal_rfid_tim_emulate(float freq) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; - TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; // basic PWM setup with needed freq and internal clock LFRFID_EMULATE_TIM.Init.Prescaler = prescaler; @@ -182,24 +181,6 @@ void furi_hal_rfid_tim_emulate(float freq) { HAL_OK) { Error_Handler(); } - - // no deadtime - sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; - sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; - sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; - sBreakDeadTimeConfig.DeadTime = 0; - sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; - sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; - sBreakDeadTimeConfig.BreakFilter = 0; - sBreakDeadTimeConfig.BreakAFMode = TIM_BREAK_AFMODE_INPUT; - sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE; - sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH; - sBreakDeadTimeConfig.Break2Filter = 0; - sBreakDeadTimeConfig.Break2AFMode = TIM_BREAK_AFMODE_INPUT; - sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; - if(HAL_TIMEx_ConfigBreakDeadTime(&LFRFID_EMULATE_TIM, &sBreakDeadTimeConfig) != HAL_OK) { - Error_Handler(); - } } void furi_hal_rfid_tim_emulate_start() { diff --git a/firmware/targets/f6/furi-hal/furi-hal-spi.c b/firmware/targets/f6/furi-hal/furi-hal-spi.c index 805b8dfb..da7c63df 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-spi.c +++ b/firmware/targets/f6/furi-hal/furi-hal-spi.c @@ -9,6 +9,8 @@ #include #include +#define TAG "FuriHalSpi" + void furi_hal_spi_init() { // Spi structure is const, but mutex is not // Need some hell-ish casting to make it work @@ -33,7 +35,7 @@ void furi_hal_spi_init() { hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); - FURI_LOG_I("FuriHalSpi", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) { diff --git a/firmware/targets/f6/furi-hal/furi-hal-subghz.c b/firmware/targets/f6/furi-hal/furi-hal-subghz.c index cd610cb2..276482ee 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-subghz.c +++ b/firmware/targets/f6/furi-hal/furi-hal-subghz.c @@ -10,6 +10,8 @@ #include #include +#define TAG "FuriHalSubGhz" + static volatile SubGhzState furi_hal_subghz_state = SubGhzStateInit; static volatile SubGhzRegulation furi_hal_subghz_regulation = SubGhzRegulationTxRx; @@ -303,7 +305,7 @@ void furi_hal_subghz_init() { cc1101_shutdown(device); furi_hal_spi_device_return(device); - FURI_LOG_I("FuriHalSubGhz", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_subghz_sleep() { diff --git a/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c b/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c index dd82cf16..e1f5de7d 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c +++ b/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c @@ -345,6 +345,7 @@ static const struct CdcConfigDescriptorDual cdc_cfg_desc_dual = { }; static struct usb_cdc_line_coding cdc_config[IF_NUM_MAX] = {}; +static uint8_t cdc_ctrl_line_state[IF_NUM_MAX]; static void cdc_init(usbd_device* dev, struct UsbInterface* intf); static void cdc_deinit(usbd_device *dev); @@ -438,6 +439,12 @@ struct usb_cdc_line_coding* furi_hal_cdc_get_port_settings(uint8_t if_num) { return NULL; } +uint8_t furi_hal_cdc_get_ctrl_line_state(uint8_t if_num) { + if (if_num < 2) + return cdc_ctrl_line_state[if_num]; + return 0; +} + void furi_hal_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len) { if (if_num == 0) usbd_ep_write(usb_dev, CDC0_TXD_EP, buf, len); @@ -465,6 +472,7 @@ static void cdc_on_wakeup(usbd_device *dev) { static void cdc_on_suspend(usbd_device *dev) { for (uint8_t i = 0; i < IF_NUM_MAX; i++) { + cdc_ctrl_line_state[i] = 0; if (callbacks[i] != NULL) { if (callbacks[i]->state_callback != NULL) callbacks[i]->state_callback(0); @@ -580,8 +588,9 @@ static usbd_respond cdc_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_cal switch(req->bRequest) { case USB_CDC_SET_CONTROL_LINE_STATE: if (callbacks[if_num] != NULL) { + cdc_ctrl_line_state[if_num] = req->wValue; if (callbacks[if_num]->ctrl_line_callback != NULL) - callbacks[if_num]->ctrl_line_callback(req->wValue); + callbacks[if_num]->ctrl_line_callback(cdc_ctrl_line_state[if_num]); } return usbd_ack; case USB_CDC_SET_LINE_CODING: diff --git a/firmware/targets/f6/furi-hal/furi-hal-usb-cdc_i.h b/firmware/targets/f6/furi-hal/furi-hal-usb-cdc_i.h index 3b181582..c4859e69 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-usb-cdc_i.h +++ b/firmware/targets/f6/furi-hal/furi-hal-usb-cdc_i.h @@ -17,6 +17,8 @@ void furi_hal_cdc_set_callbacks(uint8_t if_num, CdcCallbacks* cb); struct usb_cdc_line_coding* furi_hal_cdc_get_port_settings(uint8_t if_num); +uint8_t furi_hal_cdc_get_ctrl_line_state(uint8_t if_num); + void furi_hal_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len); int32_t furi_hal_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len); diff --git a/firmware/targets/f6/furi-hal/furi-hal-usb.c b/firmware/targets/f6/furi-hal/furi-hal-usb.c index 8c78eb8b..45a6177e 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-usb.c +++ b/firmware/targets/f6/furi-hal/furi-hal-usb.c @@ -5,6 +5,8 @@ #include "usb.h" +#define TAG "FuriHalUsb" + #define USB_RECONNECT_DELAY 500 extern struct UsbInterface usb_cdc_single; @@ -64,7 +66,7 @@ void furi_hal_usb_init(void) { HAL_NVIC_SetPriority(USB_LP_IRQn, 5, 0); NVIC_EnableIRQ(USB_LP_IRQn); - FURI_LOG_I("FuriHalUsb", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_usb_set_config(UsbMode new_mode) { @@ -81,7 +83,7 @@ void furi_hal_usb_set_config(UsbMode new_mode) { usb_if_modes[usb_config.mode_cur]->deinit(&udev); if (usb_if_modes[new_mode] != NULL) { usb_if_modes[new_mode]->init(&udev, usb_if_modes[new_mode]); - FURI_LOG_I("FuriHalUsb", "USB mode change %u -> %u", usb_config.mode_cur, new_mode); + FURI_LOG_I(TAG, "USB mode change %u -> %u", usb_config.mode_cur, new_mode); usb_config.enabled = true; usb_config.mode_cur = new_mode; } @@ -98,7 +100,7 @@ void furi_hal_usb_disable() { susp_evt(&udev, 0, 0); usbd_connect(&udev, false); usb_config.enabled = false; - FURI_LOG_I("FuriHalUsb", "USB Disable"); + FURI_LOG_I(TAG, "USB Disable"); } } @@ -106,7 +108,7 @@ void furi_hal_usb_enable() { if ((!usb_config.enabled) && (usb_if_modes[usb_config.mode_cur] != NULL)) { usbd_connect(&udev, true); usb_config.enabled = true; - FURI_LOG_I("FuriHalUsb", "USB Enable"); + FURI_LOG_I(TAG, "USB Enable"); } } diff --git a/firmware/targets/f6/furi-hal/furi-hal-vcp.c b/firmware/targets/f6/furi-hal/furi-hal-vcp.c index b0b47f46..039481f1 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-vcp.c +++ b/firmware/targets/f6/furi-hal/furi-hal-vcp.c @@ -1,32 +1,42 @@ #include - +#include #include #include +#define TAG "FuriHalVcp" + #define USB_CDC_PKT_LEN CDC_DATA_SZ +#define VCP_RX_BUF_SIZE (USB_CDC_PKT_LEN * 3) +#define VCP_TX_BUF_SIZE (USB_CDC_PKT_LEN * 3) + #define VCP_IF_NUM 0 typedef enum { - VcpConnect, - VcpDisconnect, -} VcpEvent; + VcpEvtReserved = (1 << 0), // Reserved for StreamBuffer internal event + VcpEvtConnect = (1 << 1), + VcpEvtDisconnect = (1 << 2), + VcpEvtEnable = (1 << 3), + VcpEvtDisable = (1 << 4), + VcpEvtRx = (1 << 5), + VcpEvtTx = (1 << 6), + VcpEvtStreamRx = (1 << 7), + VcpEvtStreamTx = (1 << 8), +} WorkerEvtFlags; + +#define VCP_THREAD_FLAG_ALL (VcpEvtConnect | VcpEvtDisconnect | VcpEvtEnable | VcpEvtDisable | VcpEvtRx | VcpEvtTx | VcpEvtStreamRx | VcpEvtStreamTx) typedef struct { + FuriThread* thread; + + StreamBufferHandle_t tx_stream; + StreamBufferHandle_t rx_stream; + volatile bool connected; - uint8_t rx_buf[USB_CDC_PKT_LEN]; - uint8_t rx_buf_start; - uint8_t rx_buf_len; - - osMessageQueueId_t event_queue; - - osMutexId_t usb_mutex; - - osSemaphoreId_t tx_sem; - osSemaphoreId_t rx_sem; - + uint8_t data_buffer[USB_CDC_PKT_LEN]; } FuriHalVcp; +static int32_t vcp_worker(void* context); static void vcp_on_cdc_tx_complete(); static void vcp_on_cdc_rx(); static void vcp_state_callback(uint8_t state); @@ -49,34 +59,137 @@ void furi_hal_vcp_init() { vcp = furi_alloc(sizeof(FuriHalVcp)); vcp->connected = false; - vcp->usb_mutex = osMutexNew(NULL); + vcp->tx_stream = xStreamBufferCreate(VCP_TX_BUF_SIZE, 1); + vcp->rx_stream = xStreamBufferCreate(VCP_RX_BUF_SIZE, 1); - vcp->tx_sem = osSemaphoreNew(1, 1, NULL); - vcp->rx_sem = osSemaphoreNew(1, 0, NULL); + vcp->thread = furi_thread_alloc(); + furi_thread_set_name(vcp->thread, "VcpWorker"); + furi_thread_set_stack_size(vcp->thread, 1024); + furi_thread_set_callback(vcp->thread, vcp_worker); + furi_thread_start(vcp->thread); - vcp->event_queue = osMessageQueueNew(8, sizeof(VcpEvent), NULL); + FURI_LOG_I(TAG, "Init OK"); +} + +static int32_t vcp_worker(void* context) { + bool enabled = true; + bool tx_idle = false; + size_t missed_rx = 0; furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb); - FURI_LOG_I("FuriHalVcp", "Init OK"); + while (1) { + uint32_t flags = osThreadFlagsWait(VCP_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever); + furi_assert((flags & osFlagsError) == 0); + + // New data received + if((flags & VcpEvtStreamRx) && enabled && missed_rx > 0) { +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP StreamRx\r\n"); +#endif + if (xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) { + flags |= VcpEvtRx; + missed_rx--; + } + } + + // Rx buffer was read, maybe there is enough space for new data? + if((flags & VcpEvtRx)) { + if (xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) { + int32_t len = furi_hal_cdc_receive(VCP_IF_NUM, vcp->data_buffer, USB_CDC_PKT_LEN); +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_printf("VCP Rx %d\r\n", len); +#endif + if (len > 0) { + furi_check(xStreamBufferSend(vcp->rx_stream, vcp->data_buffer, len, osWaitForever) == len); + } + } else { +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP Rx missed\r\n"); +#endif + missed_rx++; + } + } + + // New data in Tx buffer + if((flags & VcpEvtStreamTx) && enabled) { +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP StreamTx\r\n"); +#endif + if (tx_idle) { + flags |= VcpEvtTx; + } + } + + // CDC write transfer done + if((flags & VcpEvtTx) && enabled) { + size_t len = xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0); +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_printf("VCP Tx %d\r\n", len); +#endif + if (len > 0) { // Some data left in Tx buffer. Sending it now + tx_idle = false; + furi_hal_cdc_send(VCP_IF_NUM, vcp->data_buffer, len); + } else { // There is nothing to send. Set flag to start next transfer instantly + tx_idle = true; + } + } + + // VCP session opened + if((flags & VcpEvtConnect) && enabled) { +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP Connect\r\n"); +#endif + if (vcp->connected == false) { + vcp->connected = true; + xStreamBufferSend(vcp->rx_stream, &ascii_soh, 1, osWaitForever); + } + } + + // VCP session closed + if((flags & VcpEvtDisconnect) && enabled) { +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP Disconnect\r\n"); +#endif + if (vcp->connected == true) { + vcp->connected = false; + xStreamBufferSend(vcp->rx_stream, &ascii_eot, 1, osWaitForever); + } + } + + // VCP enabled + if((flags & VcpEvtEnable) && !enabled){ +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP Enable\r\n"); +#endif + furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb); + enabled = true; + furi_hal_cdc_receive(VCP_IF_NUM, vcp->data_buffer, USB_CDC_PKT_LEN); // flush Rx buffer + if (furi_hal_cdc_get_ctrl_line_state(VCP_IF_NUM) & (1 << 0)) { + vcp->connected = true; + xStreamBufferSend(vcp->rx_stream, &ascii_soh, 1, osWaitForever); + } + } + + // VCP disabled + if((flags & VcpEvtDisable) && enabled) { +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP Disable\r\n"); +#endif + enabled = false; + vcp->connected = false; + xStreamBufferSend(vcp->rx_stream, &ascii_eot, 1, osWaitForever); + } + } + return 0; } void furi_hal_vcp_enable() { - furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb); - VcpEvent evt = VcpConnect; - osMessageQueuePut(vcp->event_queue, &evt, 0, 0); - vcp->connected = true; - osSemaphoreRelease(vcp->tx_sem); - osSemaphoreRelease(vcp->rx_sem); + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtEnable); } void furi_hal_vcp_disable() { - furi_hal_cdc_set_callbacks(VCP_IF_NUM, NULL); - VcpEvent evt = VcpDisconnect; - osMessageQueuePut(vcp->event_queue, &evt, 0, 0); - vcp->connected = false; - osSemaphoreRelease(vcp->tx_sem); - osSemaphoreRelease(vcp->rx_sem); + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisable); } size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeout) { @@ -85,47 +198,17 @@ size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeo size_t rx_cnt = 0; - VcpEvent evt = VcpDisconnect; + while (size > 0) { + size_t batch_size = size; + if (batch_size > VCP_RX_BUF_SIZE) + batch_size = VCP_RX_BUF_SIZE; - if (vcp->rx_buf_len > 0) { - size_t len = (vcp->rx_buf_len > size) ? (size) : (vcp->rx_buf_len); - memcpy(&buffer[rx_cnt], &vcp->rx_buf[vcp->rx_buf_start], len); - vcp->rx_buf_len -= len; - vcp->rx_buf_start += len; - rx_cnt += len; - } - - while (rx_cnt < size) { - if (osMessageQueueGet(vcp->event_queue, &evt, NULL, 0) == osOK) { - if (evt == VcpConnect) - buffer[rx_cnt] = ascii_soh; - else { - buffer[rx_cnt] = ascii_eot; - vcp->rx_buf_len = 0; - } - rx_cnt++; - return rx_cnt; - } - - if (osSemaphoreAcquire(vcp->rx_sem, timeout) == osErrorTimeout) - return rx_cnt; - - furi_check(osMutexAcquire(vcp->usb_mutex, osWaitForever) == osOK); - size_t len = furi_hal_cdc_receive(VCP_IF_NUM, vcp->rx_buf, USB_CDC_PKT_LEN); - furi_check(osMutexRelease(vcp->usb_mutex) == osOK); - - vcp->rx_buf_len = len; - vcp->rx_buf_start = 0; - - if (vcp->rx_buf_len > (size - rx_cnt)) { - len = size - rx_cnt; - memcpy(&buffer[rx_cnt], vcp->rx_buf, len); - vcp->rx_buf_len -= len; - vcp->rx_buf_start += len; - } else { - memcpy(&buffer[rx_cnt], vcp->rx_buf, vcp->rx_buf_len); - vcp->rx_buf_len = 0; - } + size_t len = xStreamBufferReceive(vcp->rx_stream, buffer, batch_size, timeout); + if (len == 0) + break; + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStreamRx); + size -= len; + buffer += len; rx_cnt += len; } return rx_cnt; @@ -133,26 +216,20 @@ size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeo size_t furi_hal_vcp_rx(uint8_t* buffer, size_t size) { furi_assert(vcp); - - return furi_hal_vcp_rx_with_timeout(buffer, size, portMAX_DELAY); + return furi_hal_vcp_rx_with_timeout(buffer, size, osWaitForever); } void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) { furi_assert(vcp); + furi_assert(buffer); - while (size > 0 && vcp->connected) { - furi_check(osSemaphoreAcquire(vcp->tx_sem, osWaitForever) == osOK); - if (!vcp->connected) - break; - + while (size > 0) { size_t batch_size = size; - if (batch_size > USB_CDC_PKT_LEN) { - batch_size = USB_CDC_PKT_LEN; - } + if (batch_size > VCP_TX_BUF_SIZE) + batch_size = VCP_TX_BUF_SIZE; - furi_check(osMutexAcquire(vcp->usb_mutex, osWaitForever) == osOK); - furi_hal_cdc_send(VCP_IF_NUM, (uint8_t*)buffer, batch_size); - furi_check(osMutexRelease(vcp->usb_mutex) == osOK); + xStreamBufferSend(vcp->tx_stream, buffer, batch_size, osWaitForever); + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStreamTx); size -= batch_size; buffer += batch_size; @@ -160,52 +237,38 @@ void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) { } static void vcp_state_callback(uint8_t state) { - if (state == 1) { - osSemaphoreRelease(vcp->rx_sem); - //osSemaphoreRelease(vcp->tx_sem); - } - else if (vcp->connected) { - vcp->connected = false; - osSemaphoreRelease(vcp->rx_sem); - VcpEvent evt = VcpDisconnect; - osMessageQueuePut(vcp->event_queue, &evt, 0, 0); - //osSemaphoreRelease(vcp->tx_sem); +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP State\r\n"); +#endif + if (state == 0) { + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect); } } static void vcp_on_cdc_control_line(uint8_t state) { // bit 0: DTR state, bit 1: RTS state - bool dtr = state & 0b1; - - if (dtr) { - if (!vcp->connected) { - vcp->connected = true; - VcpEvent evt = VcpConnect; - osMessageQueuePut(vcp->event_queue, &evt, 0, 0); - } + bool dtr = state & (1 << 0); +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP CtrlLine\r\n"); +#endif + if (dtr == true) { + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtConnect); } else { - if (vcp->connected) { - VcpEvent evt = VcpDisconnect; - osMessageQueuePut(vcp->event_queue, &evt, 0, 0); - vcp->connected = false; - } + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect); } - - osSemaphoreRelease(vcp->tx_sem); - osSemaphoreRelease(vcp->rx_sem); } static void vcp_on_cdc_rx() { - if (vcp->connected == false) - return; - osSemaphoreRelease(vcp->rx_sem); + uint32_t ret = osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtRx); + furi_assert((ret & osFlagsError) == 0); } static void vcp_on_cdc_tx_complete() { - osSemaphoreRelease(vcp->tx_sem); + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtTx); } bool furi_hal_vcp_is_connected(void) { + furi_assert(vcp); return vcp->connected; } diff --git a/firmware/targets/f6/furi-hal/furi-hal-version.c b/firmware/targets/f6/furi-hal/furi-hal-version.c index 5b412315..8f5f26d9 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-version.c +++ b/firmware/targets/f6/furi-hal/furi-hal-version.c @@ -7,6 +7,8 @@ #include #include "ble.h" +#define TAG "FuriHalVersion" + #define FURI_HAL_VERSION_OTP_HEADER_MAGIC 0xBABE #define FURI_HAL_VERSION_OTP_ADDRESS OTP_AREA_BASE @@ -191,7 +193,7 @@ void furi_hal_version_init() { break; default: furi_crash(NULL); } - FURI_LOG_I("FuriHalVersion", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } bool furi_hal_version_do_i_belong_here() { diff --git a/firmware/targets/f6/furi-hal/furi-hal-vibro.c b/firmware/targets/f6/furi-hal/furi-hal-vibro.c index 7dfddd42..7de8ad84 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-vibro.c +++ b/firmware/targets/f6/furi-hal/furi-hal-vibro.c @@ -1,10 +1,12 @@ #include #include +#define TAG "FuriHalVibro" + void furi_hal_vibro_init() { hal_gpio_init(&vibro_gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); hal_gpio_write(&vibro_gpio, false); - FURI_LOG_I("FuriHalVibro", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } diff --git a/firmware/targets/f6/furi-hal/furi-hal.c b/firmware/targets/f6/furi-hal/furi-hal.c index aa7536ef..d435c5f2 100644 --- a/firmware/targets/f6/furi-hal/furi-hal.c +++ b/firmware/targets/f6/furi-hal/furi-hal.c @@ -5,6 +5,12 @@ #include #include +#include + +#include + +#define TAG "FuriHal" + void furi_hal_init() { furi_hal_clock_init(); furi_hal_console_init(); @@ -12,23 +18,23 @@ void furi_hal_init() { furi_hal_delay_init(); MX_GPIO_Init(); - FURI_LOG_I("HAL", "GPIO OK"); + FURI_LOG_I(TAG, "GPIO OK"); MX_RTC_Init(); - FURI_LOG_I("HAL", "RTC OK"); + FURI_LOG_I(TAG, "RTC OK"); furi_hal_bootloader_init(); furi_hal_version_init(); furi_hal_spi_init(); MX_TIM1_Init(); - FURI_LOG_I("HAL", "TIM1 OK"); + FURI_LOG_I(TAG, "TIM1 OK"); MX_TIM2_Init(); - FURI_LOG_I("HAL", "TIM2 OK"); + FURI_LOG_I(TAG, "TIM2 OK"); MX_TIM16_Init(); - FURI_LOG_I("HAL", "TIM16 OK"); + FURI_LOG_I(TAG, "TIM16 OK"); MX_COMP1_Init(); - FURI_LOG_I("HAL", "COMP1 OK"); + FURI_LOG_I(TAG, "COMP1 OK"); furi_hal_crypto_init(); @@ -36,7 +42,7 @@ void furi_hal_init() { furi_hal_usb_init(); furi_hal_usb_set_config(UsbModeVcpSingle); furi_hal_vcp_init(); - FURI_LOG_I("HAL", "USB OK"); + FURI_LOG_I(TAG, "USB OK"); furi_hal_i2c_init(); @@ -52,4 +58,22 @@ void furi_hal_init() { // FreeRTOS glue furi_hal_os_init(); + + // FatFS driver initialization + MX_FATFS_Init(); + FURI_LOG_I(TAG, "FATFS OK"); + + // Partial null pointer dereference protection + LL_MPU_Disable(); + LL_MPU_ConfigRegion( + LL_MPU_REGION_NUMBER0, 0x00, 0x0, + LL_MPU_REGION_SIZE_1MB + | LL_MPU_REGION_PRIV_RO_URO + | LL_MPU_ACCESS_BUFFERABLE + | LL_MPU_ACCESS_CACHEABLE + | LL_MPU_ACCESS_SHAREABLE + | LL_MPU_TEX_LEVEL1 + | LL_MPU_INSTRUCTION_ACCESS_ENABLE + ); + LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT); } diff --git a/firmware/targets/f6/target.mk b/firmware/targets/f6/target.mk index 0b18617e..85669e8d 100644 --- a/firmware/targets/f6/target.mk +++ b/firmware/targets/f6/target.mk @@ -49,8 +49,6 @@ C_SOURCES += \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_cortex.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_cryp.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_exti.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash_ex.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_gpio.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_hsem.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_ipcc.c \ @@ -130,6 +128,11 @@ ifeq ($(FURI_HAL_OS_DEBUG), 1) CFLAGS += -DFURI_HAL_OS_DEBUG endif +FURI_HAL_USB_VCP_DEBUG ?= 0 +ifeq ($(FURI_HAL_USB_VCP_DEBUG), 1) +CFLAGS += -DFURI_HAL_USB_VCP_DEBUG +endif + FURI_HAL_SUBGHZ_TX_GPIO ?= 0 ifneq ($(FURI_HAL_SUBGHZ_TX_GPIO), 0) CFLAGS += -DFURI_HAL_SUBGHZ_TX_GPIO=$(FURI_HAL_SUBGHZ_TX_GPIO) @@ -146,10 +149,10 @@ C_SOURCES += $(wildcard $(FURI_HAL_DIR)/*.c) # Other CFLAGS += \ -I$(MXPROJECT_DIR)/Inc \ - -I$(MXPROJECT_DIR)/Src/fatfs + -I$(MXPROJECT_DIR)/fatfs C_SOURCES += \ $(wildcard $(MXPROJECT_DIR)/Src/*.c) \ - $(wildcard $(MXPROJECT_DIR)/Src/fatfs/*.c) + $(wildcard $(MXPROJECT_DIR)/fatfs/*.c) # Linker options ifeq ($(NO_BOOTLOADER), 1) diff --git a/firmware/targets/f7/Inc/FreeRTOSConfig.h b/firmware/targets/f7/Inc/FreeRTOSConfig.h index 228b530d..1ad20993 100644 --- a/firmware/targets/f7/Inc/FreeRTOSConfig.h +++ b/firmware/targets/f7/Inc/FreeRTOSConfig.h @@ -57,7 +57,7 @@ #endif /* CMSIS_device_header */ #define configENABLE_FPU 1 -#define configENABLE_MPU 1 +#define configENABLE_MPU 0 #define configUSE_PREEMPTION 1 #define configSUPPORT_STATIC_ALLOCATION 0 @@ -101,6 +101,9 @@ #define configTIMER_TASK_PRIORITY ( 2 ) #define configTIMER_QUEUE_LENGTH 32 #define configTIMER_TASK_STACK_DEPTH 256 +#define configTIMER_SERVICE_TASK_NAME "TimersSrv" + +#define configIDLE_TASK_NAME "(-_-)" /* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */ diff --git a/firmware/targets/f7/Inc/stm32_assert.h b/firmware/targets/f7/Inc/stm32_assert.h new file mode 100644 index 00000000..9f6261ff --- /dev/null +++ b/firmware/targets/f7/Inc/stm32_assert.h @@ -0,0 +1,40 @@ +/** + ****************************************************************************** + * @file stm32_assert.h + * @brief STM32 assert file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32_ASSERT_H +#define __STM32_ASSERT_H + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef USE_FULL_ASSERT + #define assert_param(expr) ((expr) ? (void)0U : assert_failed()) + void assert_failed(); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32_ASSERT_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/Inc/stm32wbxx_hal_conf.h b/firmware/targets/f7/Inc/stm32wbxx_hal_conf.h index ab7b2953..4d5ad791 100644 --- a/firmware/targets/f7/Inc/stm32wbxx_hal_conf.h +++ b/firmware/targets/f7/Inc/stm32wbxx_hal_conf.h @@ -184,7 +184,7 @@ * @brief Uncomment the line below to expanse the "assert_param" macro in the * HAL drivers code */ -/* #define USE_FULL_ASSERT 1U */ +#define USE_FULL_ASSERT 1U /* ################## SPI peripheral configuration ########################## */ @@ -329,17 +329,8 @@ /* Exported macro ------------------------------------------------------------*/ #ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); + #define assert_param(expr) ((expr) ? (void)0U : assert_failed()) + void assert_failed(); #else #define assert_param(expr) ((void)0U) #endif /* USE_FULL_ASSERT */ diff --git a/firmware/targets/f7/Src/main.c b/firmware/targets/f7/Src/main.c index ea6d8943..a546086f 100644 --- a/firmware/targets/f7/Src/main.c +++ b/firmware/targets/f7/Src/main.c @@ -1,11 +1,11 @@ #include "main.h" -#include "fatfs/fatfs.h" - #include #include #include +#define TAG "Main" + int main(void) { // Initialize FURI layer furi_init(); @@ -16,13 +16,9 @@ int main(void) { // Flipper FURI HAL furi_hal_init(); - // 3rd party - MX_FATFS_Init(); - FURI_LOG_I("HAL", "FATFS OK"); - // CMSIS initialization osKernelInitialize(); - FURI_LOG_I("HAL", "KERNEL OK"); + FURI_LOG_I(TAG, "KERNEL OK"); // Init flipper flipper_init(); @@ -47,9 +43,6 @@ void Error_Handler(void) { * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { - /* USER CODE BEGIN 6 */ - /* User can add his own implementation to report the file name and line number, - tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ - /* USER CODE END 6 */ + furi_crash("HAL assert failed"); } #endif /* USE_FULL_ASSERT */ diff --git a/firmware/targets/f7/ble-glue/battery_service.c b/firmware/targets/f7/ble-glue/battery_service.c index 1dd8c5a0..2a5dad5e 100644 --- a/firmware/targets/f7/ble-glue/battery_service.c +++ b/firmware/targets/f7/ble-glue/battery_service.c @@ -4,7 +4,7 @@ #include -#define BATTERY_SERVICE_TAG "battery service" +#define TAG "BtBatterySvc" typedef struct { uint16_t svc_handle; @@ -23,7 +23,7 @@ void battery_svc_start() { // Add Battery service status = aci_gatt_add_service(UUID_TYPE_16, (Service_UUID_t*)&service_uuid, PRIMARY_SERVICE, 4, &battery_svc->svc_handle); if(status) { - FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed to add Battery service: %d", status); + FURI_LOG_E(TAG, "Failed to add Battery service: %d", status); } // Add Battery level characteristic status = aci_gatt_add_char(battery_svc->svc_handle, @@ -37,7 +37,7 @@ void battery_svc_start() { CHAR_VALUE_LEN_CONSTANT, &battery_svc->char_level_handle); if(status) { - FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed to add Battery level characteristic: %d", status); + FURI_LOG_E(TAG, "Failed to add Battery level characteristic: %d", status); } } @@ -47,12 +47,12 @@ void battery_svc_stop() { // Delete Battery level characteristic status = aci_gatt_del_char(battery_svc->svc_handle, battery_svc->char_level_handle); if(status) { - FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed to delete Battery level characteristic: %d", status); + FURI_LOG_E(TAG, "Failed to delete Battery level characteristic: %d", status); } // Delete Battery service status = aci_gatt_del_service(battery_svc->svc_handle); if(status) { - FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed to delete Battery service: %d", status); + FURI_LOG_E(TAG, "Failed to delete Battery service: %d", status); } free(battery_svc); battery_svc = NULL; @@ -65,14 +65,14 @@ bool battery_svc_update_level(uint8_t battery_charge) { return false; } // Update battery level characteristic - FURI_LOG_I(BATTERY_SERVICE_TAG, "Updating battery level characteristic"); + FURI_LOG_I(TAG, "Updating battery level characteristic"); tBleStatus result = aci_gatt_update_char_value(battery_svc->svc_handle, battery_svc->char_level_handle, 0, 1, &battery_charge); if(result) { - FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed updating RX characteristic: %d", result); + FURI_LOG_E(TAG, "Failed updating RX characteristic: %d", result); } return result != BLE_STATUS_SUCCESS; } diff --git a/firmware/targets/f7/ble-glue/ble_app.c b/firmware/targets/f7/ble-glue/ble_app.c index 33e5264a..40b34679 100644 --- a/firmware/targets/f7/ble-glue/ble_app.c +++ b/firmware/targets/f7/ble-glue/ble_app.c @@ -8,7 +8,7 @@ #include -#define BLE_APP_TAG "ble app" +#define TAG "Bt" PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static TL_CmdPacket_t ble_app_cmd_buffer; PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint32_t ble_app_nvm[BLE_NVM_SRAM_SIZE]; @@ -33,7 +33,7 @@ bool ble_app_init() { ble_app->hci_mtx = osMutexNew(NULL); ble_app->hci_sem = osSemaphoreNew(1, 0, NULL); // HCI transport layer thread to handle user asynch events - ble_app->hci_thread_attr.name = "ble hci"; + ble_app->hci_thread_attr.name = "BleHciWorker"; ble_app->hci_thread_attr.stack_size = 1024; ble_app->hci_thread_id = osThreadNew(ble_app_hci_thread, NULL, &ble_app->hci_thread_attr); @@ -53,7 +53,7 @@ bool ble_app_init() { }; status = SHCI_C2_Config(&config_param); if(status) { - FURI_LOG_E(BLE_APP_TAG, "Failed to configure 2nd core: %d", status); + FURI_LOG_E(TAG, "Failed to configure 2nd core: %d", status); } // Start ble stack on 2nd core @@ -82,7 +82,7 @@ bool ble_app_init() { }; status = SHCI_C2_BLE_Init(&ble_init_cmd_packet); if(status) { - FURI_LOG_E(BLE_APP_TAG, "Failed to start ble stack: %d", status); + FURI_LOG_E(TAG, "Failed to start ble stack: %d", status); } return status == SHCI_Success; } diff --git a/firmware/targets/f7/ble-glue/ble_glue.c b/firmware/targets/f7/ble-glue/ble_glue.c index 4a9c144e..45503683 100644 --- a/firmware/targets/f7/ble-glue/ble_glue.c +++ b/firmware/targets/f7/ble-glue/ble_glue.c @@ -10,6 +10,8 @@ #include "app_debug.h" #include +#define TAG "Core2" + #define POOL_SIZE (CFG_TLBLE_EVT_QUEUE_LENGTH*4U*DIVC(( sizeof(TL_PacketHeader_t) + TL_BLE_EVENT_FRAME_SIZE ), 4U)) PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_event_pool[POOL_SIZE]; @@ -17,6 +19,16 @@ PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t ble_glue_system_cmd_b PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_system_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255U]; PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_ble_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255]; +typedef enum { + // Stage 1: core2 startup and FUS + BleGlueStatusStartup, + BleGlueStatusBroken, + BleGlueStatusFusStarted, + // Stage 2: radio stack + BleGlueStatusRadioStackStarted, + BleGlueStatusRadioStackMissing +} BleGlueStatus; + typedef struct { osMutexId_t shci_mtx; osSemaphoreId_t shci_sem; @@ -33,13 +45,6 @@ static void ble_glue_user_event_thread(void *argument); static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status); static void ble_glue_sys_user_event_callback(void* pPayload); -BleGlueStatus ble_glue_get_status() { - if(!ble_glue) { - return BleGlueStatusUninitialized; - } - return ble_glue->status; -} - void ble_glue_set_key_storage_changed_callback(BleGlueKeyStorageChangedCallback callback, void* context) { furi_assert(ble_glue); furi_assert(callback); @@ -50,7 +55,7 @@ void ble_glue_set_key_storage_changed_callback(BleGlueKeyStorageChangedCallback void ble_glue_init() { ble_glue = furi_alloc(sizeof(BleGlue)); ble_glue->status = BleGlueStatusStartup; - ble_glue->shci_user_event_thread_attr.name = "ble_shci_evt"; + ble_glue->shci_user_event_thread_attr.name = "BleShciWorker"; ble_glue->shci_user_event_thread_attr.stack_size = 1024; // Configure the system Power Mode @@ -94,6 +99,68 @@ void ble_glue_init() { */ } +static bool ble_glue_wait_status(BleGlueStatus status) { + bool ret = false; + size_t countdown = 1000; + while (countdown > 0) { + if (ble_glue->status == status) { + ret = true; + break; + } + countdown--; + osDelay(1); + } + return ret; +} + +bool ble_glue_start() { + furi_assert(ble_glue); + + if (!ble_glue_wait_status(BleGlueStatusFusStarted)) { + // shutdown core2 power + FURI_LOG_E(TAG, "Core2 catastrophic failure, cutting its power"); + LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); + ble_glue->status = BleGlueStatusBroken; + furi_hal_power_insomnia_exit(); + return false; + } + + bool ret = false; + furi_hal_power_insomnia_enter(); + if(ble_app_init()) { + FURI_LOG_I(TAG, "Radio stack started"); + ble_glue->status = BleGlueStatusRadioStackStarted; + ret = true; + if(SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7) == SHCI_Success) { + FURI_LOG_I(TAG, "Flash activity control switched to SEM7"); + } else { + FURI_LOG_E(TAG, "Failed to switch flash activity control to SEM7"); + } + } else { + FURI_LOG_E(TAG, "Radio stack startup failed"); + ble_glue->status = BleGlueStatusRadioStackMissing; + } + furi_hal_power_insomnia_exit(); + + return ret; +} + +bool ble_glue_is_alive() { + if(!ble_glue) { + return false; + } + + return ble_glue->status >= BleGlueStatusFusStarted; +} + +bool ble_glue_is_radio_stack_ready() { + if(!ble_glue) { + return false; + } + + return ble_glue->status == BleGlueStatusRadioStackStarted; +} + static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status) { switch (status) { case SHCI_TL_CmdBusy: @@ -124,21 +191,11 @@ static void ble_glue_sys_user_event_callback( void * pPayload ) { TL_AsynchEvt_t *p_sys_event = (TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload); if(p_sys_event->subevtcode == SHCI_SUB_EVT_CODE_READY) { - if(ble_app_init()) { - FURI_LOG_I("Core2", "BLE stack started"); - ble_glue->status = BleGlueStatusStarted; - if(SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7) == SHCI_Success) { - FURI_LOG_I("Core2", "Flash activity control switched to SEM7"); - } else { - FURI_LOG_E("Core2", "Failed to switch flash activity control to SEM7"); - } - } else { - FURI_LOG_E("Core2", "BLE stack startup failed"); - ble_glue->status = BleGlueStatusBleStackMissing; - } + FURI_LOG_I(TAG, "Fus started"); + ble_glue->status = BleGlueStatusFusStarted; furi_hal_power_insomnia_exit(); } else if(p_sys_event->subevtcode == SHCI_SUB_EVT_ERROR_NOTIF) { - FURI_LOG_E("Core2", "Error during initialization"); + FURI_LOG_E(TAG, "Error during initialization"); furi_hal_power_insomnia_exit(); } else if(p_sys_event->subevtcode == SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE) { SHCI_C2_BleNvmRamUpdate_Evt_t* p_sys_ble_nvm_ram_update_event = (SHCI_C2_BleNvmRamUpdate_Evt_t*)p_sys_event->payload; diff --git a/firmware/targets/f7/ble-glue/ble_glue.h b/firmware/targets/f7/ble-glue/ble_glue.h index e9d6c03f..ac668c42 100644 --- a/firmware/targets/f7/ble-glue/ble_glue.h +++ b/firmware/targets/f7/ble-glue/ble_glue.h @@ -1,6 +1,7 @@ #pragma once #include +#include #ifdef __cplusplus extern "C" { @@ -8,17 +9,33 @@ extern "C" { typedef void(*BleGlueKeyStorageChangedCallback)(uint8_t* change_addr_start, uint16_t size, void* context); -typedef enum { - BleGlueStatusUninitialized, - BleGlueStatusStartup, - BleGlueStatusBleStackMissing, - BleGlueStatusStarted -} BleGlueStatus; +/** Initialize start core2 and initialize transport */ void ble_glue_init(); -BleGlueStatus ble_glue_get_status(); +/** Start Core2 Radio stack + * + * @return true on success + */ +bool ble_glue_start(); +/** Is core2 alive and at least FUS is running + * + * @return true if core2 is alive + */ +bool ble_glue_is_alive(); + +/** Is core2 radio stack present and ready + * + * @return true if present and ready + */ +bool ble_glue_is_radio_stack_ready(); + +/** Set callback for NVM in RAM changes + * + * @param[in] callback The callback to call on NVM change + * @param context The context for callback + */ void ble_glue_set_key_storage_changed_callback(BleGlueKeyStorageChangedCallback callback, void* context); #ifdef __cplusplus diff --git a/firmware/targets/f7/ble-glue/dev_info_service.c b/firmware/targets/f7/ble-glue/dev_info_service.c index 7ce2647c..64ff0509 100644 --- a/firmware/targets/f7/ble-glue/dev_info_service.c +++ b/firmware/targets/f7/ble-glue/dev_info_service.c @@ -4,7 +4,7 @@ #include -#define DEV_INFO_SVC_TAG "dev info service" +#define TAG "BtDevInfoSvc" typedef struct { uint16_t service_handle; @@ -29,7 +29,7 @@ void dev_info_svc_start() { uint16_t uuid = DEVICE_INFORMATION_SERVICE_UUID; status = aci_gatt_add_service(UUID_TYPE_16, (Service_UUID_t*)&uuid, PRIMARY_SERVICE, 9, &dev_info_svc->service_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add Device Information Service: %d", status); + FURI_LOG_E(TAG, "Failed to add Device Information Service: %d", status); } // Add characteristics @@ -45,7 +45,7 @@ void dev_info_svc_start() { CHAR_VALUE_LEN_CONSTANT, &dev_info_svc->man_name_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add manufacturer name char: %d", status); + FURI_LOG_E(TAG, "Failed to add manufacturer name char: %d", status); } uuid = SERIAL_NUMBER_UUID; status = aci_gatt_add_char(dev_info_svc->service_handle, @@ -59,7 +59,7 @@ void dev_info_svc_start() { CHAR_VALUE_LEN_CONSTANT, &dev_info_svc->serial_num_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add serial number char: %d", status); + FURI_LOG_E(TAG, "Failed to add serial number char: %d", status); } uuid = FIRMWARE_REVISION_UUID; status = aci_gatt_add_char(dev_info_svc->service_handle, @@ -73,7 +73,7 @@ void dev_info_svc_start() { CHAR_VALUE_LEN_CONSTANT, &dev_info_svc->firmware_rev_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add firmware revision char: %d", status); + FURI_LOG_E(TAG, "Failed to add firmware revision char: %d", status); } uuid = SOFTWARE_REVISION_UUID; status = aci_gatt_add_char(dev_info_svc->service_handle, @@ -87,7 +87,7 @@ void dev_info_svc_start() { CHAR_VALUE_LEN_CONSTANT, &dev_info_svc->software_rev_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to add software revision char: %d", status); + FURI_LOG_E(TAG, "Failed to add software revision char: %d", status); } // Update characteristics @@ -97,7 +97,7 @@ void dev_info_svc_start() { strlen(dev_info_man_name), (uint8_t*)dev_info_man_name); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to update manufacturer name char: %d", status); + FURI_LOG_E(TAG, "Failed to update manufacturer name char: %d", status); } status = aci_gatt_update_char_value(dev_info_svc->service_handle, dev_info_svc->serial_num_char_handle, @@ -105,7 +105,7 @@ void dev_info_svc_start() { strlen(dev_info_serial_num), (uint8_t*)dev_info_serial_num); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to update serial number char: %d", status); + FURI_LOG_E(TAG, "Failed to update serial number char: %d", status); } status = aci_gatt_update_char_value(dev_info_svc->service_handle, dev_info_svc->firmware_rev_char_handle, @@ -113,7 +113,7 @@ void dev_info_svc_start() { strlen(dev_info_firmware_rev_num), (uint8_t*)dev_info_firmware_rev_num); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to update firmware revision char: %d", status); + FURI_LOG_E(TAG, "Failed to update firmware revision char: %d", status); } status = aci_gatt_update_char_value(dev_info_svc->service_handle, dev_info_svc->software_rev_char_handle, @@ -121,7 +121,7 @@ void dev_info_svc_start() { strlen(dev_info_software_rev_num), (uint8_t*)dev_info_software_rev_num); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to update software revision char: %d", status); + FURI_LOG_E(TAG, "Failed to update software revision char: %d", status); } } @@ -131,24 +131,24 @@ void dev_info_svc_stop() { // Delete service characteristics status = aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->man_name_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete manufacturer name char: %d", status); + FURI_LOG_E(TAG, "Failed to delete manufacturer name char: %d", status); } status = aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->serial_num_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete serial number char: %d", status); + FURI_LOG_E(TAG, "Failed to delete serial number char: %d", status); } status = aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->firmware_rev_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete firmware revision char: %d", status); + FURI_LOG_E(TAG, "Failed to delete firmware revision char: %d", status); } status = aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->software_rev_char_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete software revision char: %d", status); + FURI_LOG_E(TAG, "Failed to delete software revision char: %d", status); } // Delete service status = aci_gatt_del_service(dev_info_svc->service_handle); if(status) { - FURI_LOG_E(DEV_INFO_SVC_TAG, "Failed to delete device info service: %d", status); + FURI_LOG_E(TAG, "Failed to delete device info service: %d", status); } free(dev_info_svc); dev_info_svc = NULL; diff --git a/firmware/targets/f7/ble-glue/gap.c b/firmware/targets/f7/ble-glue/gap.c index 9ddae208..2fd29f10 100644 --- a/firmware/targets/f7/ble-glue/gap.c +++ b/firmware/targets/f7/ble-glue/gap.c @@ -10,7 +10,7 @@ #include -#define GAP_TAG "BLE" +#define TAG "BtGap" #define FAST_ADV_TIMEOUT 30000 #define INITIAL_ADV_TIMEOUT 60000 @@ -80,7 +80,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt ) if (disconnection_complete_event->Connection_Handle == gap->gap_svc.connection_handle) { gap->gap_svc.connection_handle = 0; gap->state = GapStateIdle; - FURI_LOG_I(GAP_TAG, "Disconnect from client. Reason: %d", disconnection_complete_event->Reason); + FURI_LOG_I(TAG, "Disconnect from client. Reason: %d", disconnection_complete_event->Reason); } if(gap->enable_adv) { // Restart advertising @@ -96,28 +96,28 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt ) meta_evt = (evt_le_meta_event*) event_pckt->data; switch (meta_evt->subevent) { case EVT_LE_CONN_UPDATE_COMPLETE: - FURI_LOG_D(GAP_TAG, "Connection update event"); + FURI_LOG_D(TAG, "Connection update event"); break; case EVT_LE_PHY_UPDATE_COMPLETE: evt_le_phy_update_complete = (hci_le_phy_update_complete_event_rp0*)meta_evt->data; if(evt_le_phy_update_complete->Status) { - FURI_LOG_E(GAP_TAG, "Update PHY failed, status %d", evt_le_phy_update_complete->Status); + FURI_LOG_E(TAG, "Update PHY failed, status %d", evt_le_phy_update_complete->Status); } else { - FURI_LOG_I(GAP_TAG, "Update PHY succeed"); + FURI_LOG_I(TAG, "Update PHY succeed"); } ret = hci_le_read_phy(gap->gap_svc.connection_handle,&tx_phy,&rx_phy); if(ret) { - FURI_LOG_E(GAP_TAG, "Read PHY failed, status: %d", ret); + FURI_LOG_E(TAG, "Read PHY failed, status: %d", ret); } else { - FURI_LOG_I(GAP_TAG, "PHY Params TX = %d, RX = %d ", tx_phy, rx_phy); + FURI_LOG_I(TAG, "PHY Params TX = %d, RX = %d ", tx_phy, rx_phy); } break; case EVT_LE_CONN_COMPLETE: furi_hal_power_insomnia_enter(); hci_le_connection_complete_event_rp0* connection_complete_event = (hci_le_connection_complete_event_rp0 *) meta_evt->data; - FURI_LOG_I(GAP_TAG, "Connection complete for connection handle 0x%x", connection_complete_event->Connection_Handle); + FURI_LOG_I(TAG, "Connection complete for connection handle 0x%x", connection_complete_event->Connection_Handle); // Stop advertising as connection completed osTimerStop(gap->advertise_timer); @@ -141,7 +141,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt ) aci_gap_pairing_complete_event_rp0 *pairing_complete; case EVT_BLUE_GAP_LIMITED_DISCOVERABLE: - FURI_LOG_I(GAP_TAG, "Limited discoverable event"); + FURI_LOG_I(TAG, "Limited discoverable event"); break; case EVT_BLUE_GAP_PASS_KEY_REQUEST: @@ -149,39 +149,39 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt ) // Generate random PIN code uint32_t pin = rand() % 999999; aci_gap_pass_key_resp(gap->gap_svc.connection_handle, pin); - FURI_LOG_I(GAP_TAG, "Pass key request event. Pin: %d", pin); + FURI_LOG_I(TAG, "Pass key request event. Pin: %d", pin); BleEvent event = {.type = BleEventTypePinCodeShow, .data.pin_code = pin}; gap->on_event_cb(event, gap->context); } break; case EVT_BLUE_GAP_AUTHORIZATION_REQUEST: - FURI_LOG_I(GAP_TAG, "Authorization request event"); + FURI_LOG_I(TAG, "Authorization request event"); break; case EVT_BLUE_GAP_SLAVE_SECURITY_INITIATED: - FURI_LOG_I(GAP_TAG, "Slave security initiated"); + FURI_LOG_I(TAG, "Slave security initiated"); break; case EVT_BLUE_GAP_BOND_LOST: - FURI_LOG_I(GAP_TAG, "Bond lost event. Start rebonding"); + FURI_LOG_I(TAG, "Bond lost event. Start rebonding"); aci_gap_allow_rebond(gap->gap_svc.connection_handle); break; case EVT_BLUE_GAP_DEVICE_FOUND: - FURI_LOG_I(GAP_TAG, "Device found event"); + FURI_LOG_I(TAG, "Device found event"); break; case EVT_BLUE_GAP_ADDR_NOT_RESOLVED: - FURI_LOG_I(GAP_TAG, "Address not resolved event"); + FURI_LOG_I(TAG, "Address not resolved event"); break; case EVT_BLUE_GAP_KEYPRESS_NOTIFICATION: - FURI_LOG_I(GAP_TAG, "Key press notification event"); + FURI_LOG_I(TAG, "Key press notification event"); break; case EVT_BLUE_GAP_NUMERIC_COMPARISON_VALUE: - FURI_LOG_I(GAP_TAG, "Hex_value = %lx", + FURI_LOG_I(TAG, "Hex_value = %lx", ((aci_gap_numeric_comparison_value_event_rp0 *)(blue_evt->data))->Numeric_Value); aci_gap_numeric_comparison_value_confirm_yesno(gap->gap_svc.connection_handle, 1); break; @@ -189,17 +189,17 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt ) case EVT_BLUE_GAP_PAIRING_CMPLT: pairing_complete = (aci_gap_pairing_complete_event_rp0*)blue_evt->data; if (pairing_complete->Status) { - FURI_LOG_E(GAP_TAG, "Pairing failed with status: %d. Terminating connection", pairing_complete->Status); + FURI_LOG_E(TAG, "Pairing failed with status: %d. Terminating connection", pairing_complete->Status); aci_gap_terminate(gap->gap_svc.connection_handle, 5); } else { - FURI_LOG_I(GAP_TAG, "Pairing complete"); + FURI_LOG_I(TAG, "Pairing complete"); BleEvent event = {.type = BleEventTypeConnected}; gap->on_event_cb(event, gap->context); } break; case EVT_BLUE_GAP_PROCEDURE_COMPLETE: - FURI_LOG_I(GAP_TAG, "Procedure complete event"); + FURI_LOG_I(TAG, "Procedure complete event"); break; } default: @@ -286,11 +286,11 @@ static void gap_init_svc(Gap* gap) { // Set GAP characteristics status = aci_gatt_update_char_value(gap->gap_svc.gap_svc_handle, gap->gap_svc.dev_name_char_handle, 0, strlen(name), (uint8_t *) name); if (status) { - FURI_LOG_E(GAP_TAG, "Failed updating name characteristic: %d", status); + FURI_LOG_E(TAG, "Failed updating name characteristic: %d", status); } status = aci_gatt_update_char_value(gap->gap_svc.gap_svc_handle, gap->gap_svc.appearance_char_handle, 0, 2, gap_appearence_char_uuid); if(status) { - FURI_LOG_E(GAP_TAG, "Failed updating appearence characteristic: %d", status); + FURI_LOG_E(TAG, "Failed updating appearence characteristic: %d", status); } // Set default PHY hci_le_set_default_phy(ALL_PHYS_PREFERENCE, TX_2M_PREFERRED, RX_2M_PREFERRED); @@ -322,7 +322,7 @@ static void gap_advertise_start(GapState new_state) // Stop advertising status = aci_gap_set_non_discoverable(); if (status) { - FURI_LOG_E(GAP_TAG, "Stop Advertising Failed, result: %d", status); + FURI_LOG_E(TAG, "Stop Advertising Failed, result: %d", status); } } // Configure advertising @@ -331,7 +331,7 @@ static void gap_advertise_start(GapState new_state) strlen(name), (uint8_t*)name, gap->gap_svc.adv_svc_uuid_len, gap->gap_svc.adv_svc_uuid, 0, 0); if(status) { - FURI_LOG_E(GAP_TAG, "Set discoverable err: %d", status); + FURI_LOG_E(TAG, "Set discoverable err: %d", status); } gap->state = new_state; BleEvent event = {.type = BleEventTypeStartAdvertising}; @@ -355,14 +355,14 @@ static void gap_advertise_stop() { } void gap_start_advertising() { - FURI_LOG_I(GAP_TAG, "Start advertising"); + FURI_LOG_I(TAG, "Start advertising"); gap->enable_adv = true; GapCommand command = GapCommandAdvFast; furi_check(osMessageQueuePut(gap->command_queue, &command, 0, 0) == osOK); } void gap_stop_advertising() { - FURI_LOG_I(GAP_TAG, "Stop advertising"); + FURI_LOG_I(TAG, "Stop advertising"); gap->enable_adv = false; GapCommand command = GapCommandAdvStop; furi_check(osMessageQueuePut(gap->command_queue, &command, 0, 0) == osOK); @@ -374,7 +374,7 @@ static void gap_advetise_timer_callback(void* context) { } bool gap_init(BleEventCallback on_event_cb, void* context) { - if (ble_glue_get_status() != BleGlueStatusStarted) { + if (!ble_glue_is_radio_stack_ready()) { return false; } @@ -393,7 +393,7 @@ bool gap_init(BleEventCallback on_event_cb, void* context) { gap->enable_adv = true; // Thread configuration - gap->thread_attr.name = "BLE advertising"; + gap->thread_attr.name = "BleGapWorker"; gap->thread_attr.stack_size = 1024; gap->thread_id = osThreadNew(gap_app, NULL, &gap->thread_attr); diff --git a/firmware/targets/f7/ble-glue/serial_service.c b/firmware/targets/f7/ble-glue/serial_service.c index 7de3529c..c7ea6db2 100644 --- a/firmware/targets/f7/ble-glue/serial_service.c +++ b/firmware/targets/f7/ble-glue/serial_service.c @@ -4,22 +4,27 @@ #include -#define SERIAL_SERVICE_TAG "serial service" +#define TAG "BtSerialSvc" typedef struct { uint16_t svc_handle; uint16_t rx_char_handle; uint16_t tx_char_handle; + uint16_t flow_ctrl_char_handle; + osMutexId_t buff_size_mtx; + uint32_t buff_size; + uint16_t bytes_ready_to_receive; SerialSvcDataReceivedCallback on_received_cb; SerialSvcDataSentCallback on_sent_cb; void* context; } SerialSvc; -static SerialSvc* serial_svc; +static SerialSvc* serial_svc = NULL; static const uint8_t service_uuid[] = {0x00, 0x00, 0xfe, 0x60, 0xcc, 0x7a, 0x48, 0x2a, 0x98, 0x4a, 0x7f, 0x2e, 0xd5, 0xb3, 0xe5, 0x8f}; -static const uint8_t char_rx_uuid[] = {0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; static const uint8_t char_tx_uuid[] = {0x00, 0x00, 0xfe, 0x61, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; +static const uint8_t char_rx_uuid[] = {0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; +static const uint8_t flow_ctrl_uuid[] = {0x00, 0x00, 0xfe, 0x63, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void *event) { SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck; @@ -32,16 +37,26 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void *event) { if(attribute_modified->Attr_Handle == serial_svc->rx_char_handle + 2) { // Descriptor handle ret = SVCCTL_EvtAckFlowEnable; - FURI_LOG_D(SERIAL_SERVICE_TAG, "RX descriptor event"); + FURI_LOG_D(TAG, "RX descriptor event"); } else if(attribute_modified->Attr_Handle == serial_svc->rx_char_handle + 1) { - FURI_LOG_D(SERIAL_SERVICE_TAG, "Received %d bytes", attribute_modified->Attr_Data_Length); + FURI_LOG_D(TAG, "Received %d bytes", attribute_modified->Attr_Data_Length); if(serial_svc->on_received_cb) { - serial_svc->on_received_cb(attribute_modified->Attr_Data, attribute_modified->Attr_Data_Length, serial_svc->context); + furi_check(osMutexAcquire(serial_svc->buff_size_mtx, osWaitForever) == osOK); + if(attribute_modified->Attr_Data_Length > serial_svc->bytes_ready_to_receive) { + FURI_LOG_W( + TAG, "Received %d, while was ready to receive %d bytes. Can lead to buffer overflow!", + attribute_modified->Attr_Data_Length, serial_svc->bytes_ready_to_receive); + } + serial_svc->bytes_ready_to_receive -= MIN(serial_svc->bytes_ready_to_receive, attribute_modified->Attr_Data_Length); + uint32_t buff_free_size = + serial_svc->on_received_cb(attribute_modified->Attr_Data, attribute_modified->Attr_Data_Length, serial_svc->context); + FURI_LOG_D(TAG, "Available buff size: %d", buff_free_size); + furi_check(osMutexRelease(serial_svc->buff_size_mtx) == osOK); } ret = SVCCTL_EvtAckFlowEnable; } } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) { - FURI_LOG_D(SERIAL_SERVICE_TAG, "Ack received", blecore_evt->ecode); + FURI_LOG_D(TAG, "Ack received", blecore_evt->ecode); if(serial_svc->on_sent_cb) { serial_svc->on_sent_cb(serial_svc->context); } @@ -58,9 +73,9 @@ void serial_svc_start() { SVCCTL_RegisterSvcHandler(serial_svc_event_handler); // Add service - status = aci_gatt_add_service(UUID_TYPE_128, (Service_UUID_t *)service_uuid, PRIMARY_SERVICE, 6, &serial_svc->svc_handle); + status = aci_gatt_add_service(UUID_TYPE_128, (Service_UUID_t *)service_uuid, PRIMARY_SERVICE, 10, &serial_svc->svc_handle); if(status) { - FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to add Serial service: %d", status); + FURI_LOG_E(TAG, "Failed to add Serial service: %d", status); } // Add RX characteristics @@ -73,12 +88,12 @@ void serial_svc_start() { CHAR_VALUE_LEN_VARIABLE, &serial_svc->rx_char_handle); if(status) { - FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to add RX characteristic: %d", status); + FURI_LOG_E(TAG, "Failed to add RX characteristic: %d", status); } // Add TX characteristic status = aci_gatt_add_char(serial_svc->svc_handle, UUID_TYPE_128, (const Char_UUID_t*)char_tx_uuid, - SERIAL_SVC_DATA_LEN_MAX, + SERIAL_SVC_DATA_LEN_MAX, CHAR_PROP_READ | CHAR_PROP_INDICATE, ATTR_PERMISSION_AUTHEN_READ, GATT_DONT_NOTIFY_EVENTS, @@ -86,14 +101,47 @@ void serial_svc_start() { CHAR_VALUE_LEN_VARIABLE, &serial_svc->tx_char_handle); if(status) { - FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to add TX characteristic: %d", status); + FURI_LOG_E(TAG, "Failed to add TX characteristic: %d", status); } + // Add Flow Control characteristic + status = aci_gatt_add_char(serial_svc->svc_handle, UUID_TYPE_128, (const Char_UUID_t*)flow_ctrl_uuid, + sizeof(uint32_t), + CHAR_PROP_READ | CHAR_PROP_NOTIFY, + ATTR_PERMISSION_AUTHEN_READ, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_CONSTANT, + &serial_svc->flow_ctrl_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add Flow Control characteristic: %d", status); + } + // Allocate buffer size mutex + serial_svc->buff_size_mtx = osMutexNew(NULL); } -void serial_svc_set_callbacks(SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context) { +void serial_svc_set_callbacks(uint16_t buff_size, SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context) { + furi_assert(serial_svc); serial_svc->on_received_cb = on_received_cb; serial_svc->on_sent_cb = on_sent_cb; serial_svc->context = context; + serial_svc->buff_size = buff_size; + serial_svc->bytes_ready_to_receive = buff_size; + uint32_t buff_size_reversed = REVERSE_BYTES_U32(serial_svc->buff_size); + aci_gatt_update_char_value(serial_svc->svc_handle, serial_svc->flow_ctrl_char_handle, 0, sizeof(uint32_t), (uint8_t*)&buff_size_reversed); +} + +void serial_svc_notify_buffer_is_empty() { + furi_assert(serial_svc); + furi_assert(serial_svc->buff_size_mtx); + + furi_check(osMutexAcquire(serial_svc->buff_size_mtx, osWaitForever) == osOK); + if(serial_svc->bytes_ready_to_receive == 0) { + FURI_LOG_D(TAG, "Buffer is empty. Notifying client"); + serial_svc->bytes_ready_to_receive = serial_svc->buff_size; + uint32_t buff_size_reversed = REVERSE_BYTES_U32(serial_svc->buff_size); + aci_gatt_update_char_value(serial_svc->svc_handle, serial_svc->flow_ctrl_char_handle, 0, sizeof(uint32_t), (uint8_t*)&buff_size_reversed); + } + furi_check(osMutexRelease(serial_svc->buff_size_mtx) == osOK); } void serial_svc_stop() { @@ -102,17 +150,23 @@ void serial_svc_stop() { // Delete characteristics status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->tx_char_handle); if(status) { - FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to delete TX characteristic: %d", status); + FURI_LOG_E(TAG, "Failed to delete TX characteristic: %d", status); } status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->rx_char_handle); if(status) { - FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to delete RX characteristic: %d", status); + FURI_LOG_E(TAG, "Failed to delete RX characteristic: %d", status); + } + status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->flow_ctrl_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete Flow Control characteristic: %d", status); } // Delete service status = aci_gatt_del_service(serial_svc->svc_handle); if(status) { - FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to delete Serial service: %d", status); + FURI_LOG_E(TAG, "Failed to delete Serial service: %d", status); } + // Delete buffer size mutex + osMutexDelete(serial_svc->buff_size_mtx); free(serial_svc); serial_svc = NULL; } @@ -122,14 +176,13 @@ bool serial_svc_update_tx(uint8_t* data, uint8_t data_len) { if(data_len > SERIAL_SVC_DATA_LEN_MAX) { return false; } - FURI_LOG_D(SERIAL_SERVICE_TAG, "Updating char %d len", data_len); tBleStatus result = aci_gatt_update_char_value(serial_svc->svc_handle, serial_svc->tx_char_handle, 0, data_len, data); if(result) { - FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed updating TX characteristic: %d", result); + FURI_LOG_E(TAG, "Failed updating TX characteristic: %d", result); } return result != BLE_STATUS_SUCCESS; } diff --git a/firmware/targets/f7/ble-glue/serial_service.h b/firmware/targets/f7/ble-glue/serial_service.h index b5a1c078..0aa4c79f 100644 --- a/firmware/targets/f7/ble-glue/serial_service.h +++ b/firmware/targets/f7/ble-glue/serial_service.h @@ -9,12 +9,14 @@ extern "C" { #endif -typedef void(*SerialSvcDataReceivedCallback)(uint8_t* buff, uint16_t size, void* context); +typedef uint16_t(*SerialSvcDataReceivedCallback)(uint8_t* buff, uint16_t size, void* context); typedef void(*SerialSvcDataSentCallback)(void* context); void serial_svc_start(); -void serial_svc_set_callbacks(SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context); +void serial_svc_set_callbacks(uint16_t buff_size, SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context); + +void serial_svc_notify_buffer_is_empty(); void serial_svc_stop(); diff --git a/firmware/targets/f7/Src/fatfs/fatfs.c b/firmware/targets/f7/fatfs/fatfs.c similarity index 100% rename from firmware/targets/f7/Src/fatfs/fatfs.c rename to firmware/targets/f7/fatfs/fatfs.c diff --git a/firmware/targets/f7/Src/fatfs/fatfs.h b/firmware/targets/f7/fatfs/fatfs.h similarity index 100% rename from firmware/targets/f7/Src/fatfs/fatfs.h rename to firmware/targets/f7/fatfs/fatfs.h diff --git a/firmware/targets/f7/Src/fatfs/ffconf.h b/firmware/targets/f7/fatfs/ffconf.h similarity index 100% rename from firmware/targets/f7/Src/fatfs/ffconf.h rename to firmware/targets/f7/fatfs/ffconf.h diff --git a/firmware/targets/f7/Src/fatfs/spi_sd_hal.c b/firmware/targets/f7/fatfs/spi_sd_hal.c similarity index 100% rename from firmware/targets/f7/Src/fatfs/spi_sd_hal.c rename to firmware/targets/f7/fatfs/spi_sd_hal.c diff --git a/firmware/targets/f7/Src/fatfs/stm32_adafruit_sd.c b/firmware/targets/f7/fatfs/stm32_adafruit_sd.c similarity index 100% rename from firmware/targets/f7/Src/fatfs/stm32_adafruit_sd.c rename to firmware/targets/f7/fatfs/stm32_adafruit_sd.c diff --git a/firmware/targets/f7/Src/fatfs/stm32_adafruit_sd.h b/firmware/targets/f7/fatfs/stm32_adafruit_sd.h similarity index 100% rename from firmware/targets/f7/Src/fatfs/stm32_adafruit_sd.h rename to firmware/targets/f7/fatfs/stm32_adafruit_sd.h diff --git a/firmware/targets/f7/Src/fatfs/syscall.c b/firmware/targets/f7/fatfs/syscall.c similarity index 100% rename from firmware/targets/f7/Src/fatfs/syscall.c rename to firmware/targets/f7/fatfs/syscall.c diff --git a/firmware/targets/f7/Src/fatfs/user_diskio.c b/firmware/targets/f7/fatfs/user_diskio.c similarity index 100% rename from firmware/targets/f7/Src/fatfs/user_diskio.c rename to firmware/targets/f7/fatfs/user_diskio.c diff --git a/firmware/targets/f7/Src/fatfs/user_diskio.h b/firmware/targets/f7/fatfs/user_diskio.h similarity index 100% rename from firmware/targets/f7/Src/fatfs/user_diskio.h rename to firmware/targets/f7/fatfs/user_diskio.h diff --git a/firmware/targets/f7/furi-hal/furi-hal-bootloader.c b/firmware/targets/f7/furi-hal/furi-hal-bootloader.c index 2962877e..e8ea913e 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-bootloader.c +++ b/firmware/targets/f7/furi-hal/furi-hal-bootloader.c @@ -2,6 +2,8 @@ #include #include +#define TAG "FuriHalBoot" + // Boot request enum #define BOOT_REQUEST_TAINTED 0x00000000 #define BOOT_REQUEST_CLEAN 0xDADEDADE @@ -11,7 +13,7 @@ void furi_hal_bootloader_init() { #ifndef DEBUG LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_TAINTED); #endif - FURI_LOG_I("FuriHalBoot", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_bootloader_set_mode(FuriHalBootloaderMode mode) { diff --git a/firmware/targets/f7/furi-hal/furi-hal-bt.c b/firmware/targets/f7/furi-hal/furi-hal-bt.c index a018085c..b74a9e29 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-bt.c +++ b/firmware/targets/f7/furi-hal/furi-hal-bt.c @@ -6,36 +6,41 @@ #include +#define TAG "FuriHalBt" + osMutexId_t furi_hal_bt_core2_mtx = NULL; void furi_hal_bt_init() { furi_hal_bt_core2_mtx = osMutexNew(NULL); + furi_assert(furi_hal_bt_core2_mtx); + + // Explicitly tell that we are in charge of CLK48 domain + HAL_HSEM_FastTake(CFG_HW_CLK48_CONFIG_SEMID); + + // Start Core2 + ble_glue_init(); } -static bool furi_hal_bt_wait_startup() { - uint16_t counter = 0; - while (!(ble_glue_get_status() == BleGlueStatusStarted || ble_glue_get_status() == BleGlueStatusBleStackMissing)) { - osDelay(10); - counter++; - if (counter > 1000) { - return false; - } - } - return true; +void furi_hal_bt_lock_core2() { + furi_assert(furi_hal_bt_core2_mtx); + furi_check(osMutexAcquire(furi_hal_bt_core2_mtx, osWaitForever) == osOK); +} + +void furi_hal_bt_unlock_core2() { + furi_assert(furi_hal_bt_core2_mtx); + furi_check(osMutexRelease(furi_hal_bt_core2_mtx) == osOK); } bool furi_hal_bt_start_core2() { furi_assert(furi_hal_bt_core2_mtx); - bool ret = false; osMutexAcquire(furi_hal_bt_core2_mtx, osWaitForever); // Explicitly tell that we are in charge of CLK48 domain HAL_HSEM_FastTake(CFG_HW_CLK48_CONFIG_SEMID); // Start Core2 - ble_glue_init(); - // Wait for Core2 start - ret = furi_hal_bt_wait_startup(); + bool ret = ble_glue_start(); osMutexRelease(furi_hal_bt_core2_mtx); + return ret; } @@ -59,8 +64,12 @@ void furi_hal_bt_stop_advertising() { } } -void furi_hal_bt_set_data_event_callbacks(SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context) { - serial_svc_set_callbacks(on_received_cb, on_sent_cb, context); +void furi_hal_bt_set_data_event_callbacks(uint16_t buff_size, SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context) { + serial_svc_set_callbacks(buff_size, on_received_cb, on_sent_cb, context); +} + +void furi_hal_bt_notify_buffer_is_empty() { + serial_svc_notify_buffer_is_empty(); } bool furi_hal_bt_tx(uint8_t* data, uint16_t size) { @@ -70,14 +79,8 @@ bool furi_hal_bt_tx(uint8_t* data, uint16_t size) { return serial_svc_update_tx(data, size); } -bool furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size) { - bool ret = false; - BleGlueStatus status = ble_glue_get_status(); - if(status == BleGlueStatusUninitialized || BleGlueStatusStarted) { - ble_app_get_key_storage_buff(key_buff_addr, key_buff_size); - ret = true; - } - return ret; +void furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size) { + ble_app_get_key_storage_buff(key_buff_addr, key_buff_size); } void furi_hal_bt_set_key_storage_change_callback(BleGlueKeyStorageChangedCallback callback, void* context) { @@ -96,8 +99,7 @@ void furi_hal_bt_nvm_sram_sem_release() { } void furi_hal_bt_dump_state(string_t buffer) { - BleGlueStatus status = ble_glue_get_status(); - if (status == BleGlueStatusStarted) { + if (furi_hal_bt_is_alive()) { uint8_t HCI_Version; uint16_t HCI_Revision; uint8_t LMP_PAL_Version; @@ -118,99 +120,13 @@ void furi_hal_bt_dump_state(string_t buffer) { } bool furi_hal_bt_is_alive() { - BleGlueStatus status = ble_glue_get_status(); - return (status == BleGlueStatusBleStackMissing) || (status == BleGlueStatusStarted); + return ble_glue_is_alive(); } bool furi_hal_bt_is_active() { return gap_get_state() > GapStateIdle; } -static void furi_hal_bt_lock_flash_core2(bool erase_flag) { - // Take flash controller ownership - while (HAL_HSEM_FastTake(CFG_HW_FLASH_SEMID) != HAL_OK) { - taskYIELD(); - } - - // Unlock flash operation - HAL_FLASH_Unlock(); - - // Erase activity notification - if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON); - - while(true) { - // Wait till flash controller become usable - while(LL_FLASH_IsActiveFlag_OperationSuspended()) { - taskYIELD(); - }; - - // Just a little more love - taskENTER_CRITICAL(); - - // Actually we already have mutex for it, but specification is specification - if (HAL_HSEM_IsSemTaken(CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID)) { - taskEXIT_CRITICAL(); - continue; - } - - // Take sempahopre and prevent core2 from anyting funky - if (HAL_HSEM_FastTake(CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID) != HAL_OK) { - taskEXIT_CRITICAL(); - continue; - } - - break; - } -} - -void furi_hal_bt_lock_flash(bool erase_flag) { - // Acquire dangerous ops mutex - osMutexAcquire(furi_hal_bt_core2_mtx, osWaitForever); - - // If Core2 is running use IPC locking - BleGlueStatus status = ble_glue_get_status(); - if(status == BleGlueStatusStarted || status == BleGlueStatusBleStackMissing) { - furi_hal_bt_lock_flash_core2(erase_flag); - } else { - HAL_FLASH_Unlock(); - } -} - -static void furi_hal_bt_unlock_flash_core2(bool erase_flag) { - // Funky ops are ok at this point - HAL_HSEM_Release(CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID, 0); - - // Task switching is ok - taskEXIT_CRITICAL(); - - // Doesn't make much sense, does it? - while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { - taskYIELD(); - } - - // Erase activity over, core2 can continue - if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF); - - // Lock flash controller - HAL_FLASH_Lock(); - - // Release flash controller ownership - HAL_HSEM_Release(CFG_HW_FLASH_SEMID, 0); -} - -void furi_hal_bt_unlock_flash(bool erase_flag) { - // If Core2 is running use IPC locking - BleGlueStatus status = ble_glue_get_status(); - if(status == BleGlueStatusStarted || status == BleGlueStatusBleStackMissing) { - furi_hal_bt_unlock_flash_core2(erase_flag); - } else { - HAL_FLASH_Lock(); - } - - // Release dangerous ops mutex - osMutexRelease(furi_hal_bt_core2_mtx); -} - void furi_hal_bt_start_tone_tx(uint8_t channel, uint8_t power) { aci_hal_set_tx_power_level(0, power); aci_hal_tone_start(channel, 0); diff --git a/firmware/targets/f7/furi-hal/furi-hal-clock.c b/firmware/targets/f7/furi-hal/furi-hal-clock.c index fd4899d4..7a124049 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-clock.c +++ b/firmware/targets/f7/furi-hal/furi-hal-clock.c @@ -5,6 +5,8 @@ #include #include +#define TAG "FuriHalClock" + #define HS_CLOCK_IS_READY() (LL_RCC_HSE_IsReady() && LL_RCC_HSI_IsReady()) #define LS_CLOCK_IS_READY() (LL_RCC_LSE_IsReady() && LL_RCC_LSI1_IsReady()) @@ -123,7 +125,7 @@ void furi_hal_clock_init() { // APB2 LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1); - FURI_LOG_I("FuriHalClock", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_clock_switch_to_hsi() { diff --git a/firmware/targets/f7/furi-hal/furi-hal-compress.c b/firmware/targets/f7/furi-hal/furi-hal-compress.c index 9b7678f5..eb6e9d51 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-compress.c +++ b/firmware/targets/f7/furi-hal/furi-hal-compress.c @@ -4,6 +4,8 @@ #include #include +#define TAG "FuriHalCompress" + #define FURI_HAL_COMPRESS_ICON_ENCODED_BUFF_SIZE (512) #define FURI_HAL_COMPRESS_ICON_DECODED_BUFF_SIZE (1024) @@ -46,7 +48,7 @@ void furi_hal_compress_icon_init() { FURI_HAL_COMPRESS_LOOKAHEAD_BUFF_SIZE_LOG); heatshrink_decoder_reset(icon_decoder->decoder); memset(icon_decoder->decoded_buff, 0, sizeof(icon_decoder->decoded_buff)); - FURI_LOG_I("FuriHalCompress", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_compress_icon_decode(const uint8_t* icon_data, uint8_t** decoded_buff) { diff --git a/firmware/targets/f7/furi-hal/furi-hal-console.c b/firmware/targets/f7/furi-hal/furi-hal-console.c index ffe340b9..993b498e 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-console.c +++ b/firmware/targets/f7/furi-hal/furi-hal-console.c @@ -6,8 +6,12 @@ #include #include +#include + #include +#define TAG "FuriHalConsole" + #define CONSOLE_BAUDRATE 230400 volatile bool furi_hal_console_alive = false; @@ -16,7 +20,7 @@ void furi_hal_console_init() { furi_hal_uart_init(FuriHalUartIdUSART1, CONSOLE_BAUDRATE); furi_hal_console_alive = true; - FURI_LOG_I("FuriHalConsole", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_console_enable() { @@ -35,22 +39,26 @@ void furi_hal_console_tx(const uint8_t* buffer, size_t buffer_size) { if (!furi_hal_console_alive) return; + UTILS_ENTER_CRITICAL_SECTION(); // Transmit data furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)buffer, buffer_size); // Wait for TC flag to be raised for last char while (!LL_USART_IsActiveFlag_TC(USART1)); + UTILS_EXIT_CRITICAL_SECTION(); } void furi_hal_console_tx_with_new_line(const uint8_t* buffer, size_t buffer_size) { if (!furi_hal_console_alive) return; + UTILS_ENTER_CRITICAL_SECTION(); // Transmit data furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)buffer, buffer_size); // Transmit new line symbols furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)"\r\n", 2); // Wait for TC flag to be raised for last char while (!LL_USART_IsActiveFlag_TC(USART1)); + UTILS_EXIT_CRITICAL_SECTION(); } void furi_hal_console_printf(const char format[], ...) { diff --git a/firmware/targets/f7/furi-hal/furi-hal-crypto.c b/firmware/targets/f7/furi-hal/furi-hal-crypto.c index 648f3f18..91875d23 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-crypto.c +++ b/firmware/targets/f7/furi-hal/furi-hal-crypto.c @@ -3,10 +3,12 @@ #include #include +#define TAG "FuriHalCrypto" + CRYP_HandleTypeDef crypt; void furi_hal_crypto_init() { - FURI_LOG_I("FuriHalCrypto", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } bool furi_hal_crypto_store_add_key(FuriHalCryptoKey* key, uint8_t* slot) { diff --git a/firmware/targets/f7/furi-hal/furi-hal-delay.c b/firmware/targets/f7/furi-hal/furi-hal-delay.c index 52de8715..b5f3c334 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-delay.c +++ b/firmware/targets/f7/furi-hal/furi-hal-delay.c @@ -3,6 +3,8 @@ #include #include +#define TAG "FuriHalDelay" + static uint32_t clk_per_microsecond; void furi_hal_delay_init(void) { @@ -10,7 +12,7 @@ void furi_hal_delay_init(void) { DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; DWT->CYCCNT = 0U; clk_per_microsecond = SystemCoreClock / 1000000.0f; - FURI_LOG_I("FuriHalDelay", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void delay_us(float microseconds) { diff --git a/firmware/targets/f7/furi-hal/furi-hal-flash.c b/firmware/targets/f7/furi-hal/furi-hal-flash.c index 1e270bc0..156a26a9 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-flash.c +++ b/firmware/targets/f7/furi-hal/furi-hal-flash.c @@ -1,12 +1,11 @@ #include #include #include +#include +#include #include -/* Free flash space borders, exported by linker */ -extern const void __free_flash_start__; - #define FURI_HAL_TAG "FuriHalFlash" #define FURI_HAL_CRITICAL_MSG "Critical flash operation fail" #define FURI_HAL_FLASH_READ_BLOCK 8 @@ -14,6 +13,9 @@ extern const void __free_flash_start__; #define FURI_HAL_FLASH_PAGE_SIZE 4096 #define FURI_HAL_FLASH_CYCLES_COUNT 10000 +/* Free flash space borders, exported by linker */ +extern const void __free_flash_start__; + size_t furi_hal_flash_get_base() { return FLASH_BASE; } @@ -39,9 +41,9 @@ const void* furi_hal_flash_get_free_start_address() { } const void* furi_hal_flash_get_free_end_address() { - FLASH_OBProgramInitTypeDef pOBInit; - HAL_FLASHEx_OBGetConfig(&pOBInit); - return (const void *)pOBInit.SecureFlashStartAddr; + uint32_t sfr_reg_val = READ_REG(FLASH->SFR); + uint32_t sfsa = (READ_BIT(sfr_reg_val, FLASH_SFR_SFSA) >> FLASH_SFR_SFSA_Pos); + return (const void *)((sfsa * FLASH_PAGE_SIZE) + FLASH_BASE); } size_t furi_hal_flash_get_free_page_start_address() { @@ -59,47 +61,239 @@ size_t furi_hal_flash_get_free_page_count() { return (end-page_start) / FURI_HAL_FLASH_PAGE_SIZE; } -bool furi_hal_flash_erase(uint8_t page, uint8_t count) { - furi_hal_bt_lock_flash(true); +static void furi_hal_flash_unlock() { + /* verify Flash is locked */ + furi_check(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U); - FLASH_EraseInitTypeDef erase; - erase.TypeErase = FLASH_TYPEERASE_PAGES; - erase.Page = page; - erase.NbPages = count; + /* Authorize the FLASH Registers access */ + WRITE_REG(FLASH->KEYR, FLASH_KEY1); + WRITE_REG(FLASH->KEYR, FLASH_KEY2); - uint32_t error_page = 0; - HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase, &error_page); - if (status != HAL_OK) { - FURI_LOG_E(FURI_HAL_TAG, "Erase failed, ret: %d, page: %d", status, error_page); - furi_crash(FURI_HAL_CRITICAL_MSG); + /* verify Flash is unlock */ + furi_check(READ_BIT(FLASH->CR, FLASH_CR_LOCK) == 0U); +} + +static void furi_hal_flash_lock(void) { + /* verify Flash is unlocked */ + furi_check(READ_BIT(FLASH->CR, FLASH_CR_LOCK) == 0U); + + /* Set the LOCK Bit to lock the FLASH Registers access */ + /* @Note The lock and unlock procedure is done only using CR registers even from CPU2 */ + SET_BIT(FLASH->CR, FLASH_CR_LOCK); + + /* verify Flash is locked */ + furi_check(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U); +} + +static void furi_hal_flash_begin_with_core2(bool erase_flag) { + // Take flash controller ownership + while (HAL_HSEM_FastTake(CFG_HW_FLASH_SEMID) != HAL_OK) { + taskYIELD(); } - furi_hal_bt_unlock_flash(true); + // Unlock flash operation + furi_hal_flash_unlock(); + + // Erase activity notification + if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON); + + while(true) { + // Wait till flash controller become usable + while(LL_FLASH_IsActiveFlag_OperationSuspended()) { + taskYIELD(); + }; + + // Just a little more love + taskENTER_CRITICAL(); + + // Actually we already have mutex for it, but specification is specification + if (HAL_HSEM_IsSemTaken(CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID)) { + taskEXIT_CRITICAL(); + continue; + } + + // Take sempahopre and prevent core2 from anyting funky + if (HAL_HSEM_FastTake(CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID) != HAL_OK) { + taskEXIT_CRITICAL(); + continue; + } + + break; + } +} + +static void furi_hal_flash_begin(bool erase_flag) { + // Acquire dangerous ops mutex + furi_hal_bt_lock_core2(); + + // If Core2 is running use IPC locking + if(furi_hal_bt_is_alive()) { + furi_hal_flash_begin_with_core2(erase_flag); + } else { + furi_hal_flash_unlock(); + } +} + +static void furi_hal_flash_end_with_core2(bool erase_flag) { + // Funky ops are ok at this point + HAL_HSEM_Release(CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID, 0); + + // Task switching is ok + taskEXIT_CRITICAL(); + + // Doesn't make much sense, does it? + while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + taskYIELD(); + } + + // Erase activity over, core2 can continue + if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF); + + // Lock flash controller + furi_hal_flash_lock(); + + // Release flash controller ownership + HAL_HSEM_Release(CFG_HW_FLASH_SEMID, 0); +} + +static void furi_hal_flash_end(bool erase_flag) { + // If Core2 is running use IPC locking + if(furi_hal_bt_is_alive()) { + furi_hal_flash_end_with_core2(erase_flag); + } else { + furi_hal_flash_lock(); + } + + // Release dangerous ops mutex + furi_hal_bt_unlock_core2(); +} + +static void furi_hal_flush_cache(void) { + /* Flush instruction cache */ + if (READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) == FLASH_ACR_ICEN) { + /* Disable instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); + /* Reset instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_RESET(); + /* Enable instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_ENABLE(); + } + + /* Flush data cache */ + if (READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) == FLASH_ACR_DCEN) { + /* Disable data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + /* Reset data cache */ + __HAL_FLASH_DATA_CACHE_RESET(); + /* Enable data cache */ + __HAL_FLASH_DATA_CACHE_ENABLE(); + } +} + +HAL_StatusTypeDef furi_hal_flash_wait_last_operation(uint32_t timeout) { + uint32_t error = 0; + uint32_t countdown = 0; + + // Wait for the FLASH operation to complete by polling on BUSY flag to be reset. + // Even if the FLASH operation fails, the BUSY flag will be reset and an error + // flag will be set + countdown = timeout; + while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + if(LL_SYSTICK_IsActiveCounterFlag()) { + countdown--; + } + if (countdown == 0) { + return HAL_TIMEOUT; + } + } + + /* Check FLASH operation error flags */ + error = FLASH->SR; + + /* Check FLASH End of Operation flag */ + if ((error & FLASH_FLAG_EOP) != 0U) { + /* Clear FLASH End of Operation pending bit */ + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); + } + + /* Now update error variable to only error value */ + error &= FLASH_FLAG_SR_ERRORS; + + furi_check(error == 0); + + /* clear error flags */ + __HAL_FLASH_CLEAR_FLAG(error); + + /* Wait for control register to be written */ + countdown = timeout; + while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY)) { + if(LL_SYSTICK_IsActiveCounterFlag()) { + countdown--; + } + if (countdown == 0) { + return HAL_TIMEOUT; + } + } + + return HAL_OK; +} + +bool furi_hal_flash_erase(uint8_t page) { + furi_hal_flash_begin(true); + + // Ensure that controller state is valid + furi_check(FLASH->SR == 0); + + /* Verify that next operation can be proceed */ + furi_check(furi_hal_flash_wait_last_operation(FLASH_TIMEOUT_VALUE) == HAL_OK); + + /* Select page and start operation */ + MODIFY_REG(FLASH->CR, FLASH_CR_PNB, ((page << FLASH_CR_PNB_Pos) | FLASH_CR_PER | FLASH_CR_STRT)); + + /* Wait for last operation to be completed */ + furi_check(furi_hal_flash_wait_last_operation(FLASH_TIMEOUT_VALUE) == HAL_OK); + + /* If operation is completed or interrupted, disable the Page Erase Bit */ + CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB)); + + /* Flush the caches to be sure of the data consistency */ + furi_hal_flush_cache(); + + furi_hal_flash_end(true); return true; } bool furi_hal_flash_write_dword(size_t address, uint64_t data) { - furi_hal_bt_lock_flash(false); + furi_hal_flash_begin(false); - HAL_StatusTypeDef status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data); - if (status != HAL_OK) { - FURI_LOG_E(FURI_HAL_TAG, "Programming failed, ret: %d, address: %p", status, address); - furi_crash(FURI_HAL_CRITICAL_MSG); - } + // Ensure that controller state is valid + furi_check(FLASH->SR == 0); - furi_hal_bt_unlock_flash(false); - - return true; -} - -bool furi_hal_flash_write_row(size_t address, size_t source_address) { - furi_hal_bt_lock_flash(false); - - HAL_StatusTypeDef status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST, address, source_address); - furi_check(status == HAL_OK); - - furi_hal_bt_unlock_flash(false); + /* Check the parameters */ + furi_check(IS_ADDR_ALIGNED_64BITS(address)); + furi_check(IS_FLASH_PROGRAM_ADDRESS(address)); + + /* Set PG bit */ + SET_BIT(FLASH->CR, FLASH_CR_PG); + + /* Program first word */ + *(uint32_t *)address = (uint32_t)data; + + // Barrier to ensure programming is performed in 2 steps, in right order + // (independently of compiler optimization behavior) + __ISB(); + + /* Program second word */ + *(uint32_t *)(address + 4U) = (uint32_t)(data >> 32U); + + /* Wait for last operation to be completed */ + furi_check(furi_hal_flash_wait_last_operation(FLASH_TIMEOUT_VALUE) == HAL_OK); + + /* If the program operation is completed, disable the PG or FSTPG Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_PG); + + furi_hal_flash_end(false); return true; } diff --git a/firmware/targets/f7/furi-hal/furi-hal-flash.h b/firmware/targets/f7/furi-hal/furi-hal-flash.h index 92a65a65..3d8031e6 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-flash.h +++ b/firmware/targets/f7/furi-hal/furi-hal-flash.h @@ -60,18 +60,17 @@ size_t furi_hal_flash_get_free_page_count(); /** Erase Flash * - * Locking operation, uses HSEM to manage shared access. + * @warning locking operation with critical section, stales execution * - * @param page page number - * @param count page count to erase + * @param page The page to erase * * @return true on success */ -bool furi_hal_flash_erase(uint8_t page, uint8_t count); +bool furi_hal_flash_erase(uint8_t page); /** Write double word (64 bits) * - * Locking operation, uses HSEM to manage shared access. + * @warning locking operation with critical section, stales execution * * @param address destination address, must be double word aligned. * @param data data to write @@ -80,13 +79,3 @@ bool furi_hal_flash_erase(uint8_t page, uint8_t count); */ bool furi_hal_flash_write_dword(size_t address, uint64_t data); -/** Write row: 64 double word (64 bits) from address - * - * Locking operation, uses HSEM to manage shared access. - * - * @param address destination address, must be block aligned - * @param source_address source address - * - * @return true on success - */ -bool furi_hal_flash_write_row(size_t address, size_t source_address); diff --git a/firmware/targets/f7/furi-hal/furi-hal-i2c.c b/firmware/targets/f7/furi-hal/furi-hal-i2c.c index 196a2a7b..b1ec4711 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-i2c.c +++ b/firmware/targets/f7/furi-hal/furi-hal-i2c.c @@ -6,6 +6,8 @@ #include #include +#define TAG "FuriHalI2C" + osMutexId_t furi_hal_i2c_mutex = NULL; void furi_hal_i2c_init() { @@ -42,7 +44,7 @@ void furi_hal_i2c_init() { LL_I2C_DisableOwnAddress2(POWER_I2C); LL_I2C_DisableGeneralCall(POWER_I2C); LL_I2C_EnableClockStretching(POWER_I2C); - FURI_LOG_I("FuriHalI2C", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } bool furi_hal_i2c_tx( diff --git a/firmware/targets/f7/furi-hal/furi-hal-interrupt.c b/firmware/targets/f7/furi-hal/furi-hal-interrupt.c index 47e99c9f..2685edab 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-interrupt.c +++ b/firmware/targets/f7/furi-hal/furi-hal-interrupt.c @@ -4,6 +4,8 @@ #include #include +#define TAG "FuriHalInterrupt" + volatile FuriHalInterruptISR furi_hal_tim_tim2_isr = NULL; volatile FuriHalInterruptISR furi_hal_tim_tim1_isr = NULL; @@ -22,7 +24,7 @@ void furi_hal_interrupt_init() { NVIC_SetPriority(DMA1_Channel1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); NVIC_EnableIRQ(DMA1_Channel1_IRQn); - FURI_LOG_I("FuriHalInterrupt", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_interrupt_set_timer_isr(TIM_TypeDef* timer, FuriHalInterruptISR isr) { @@ -161,10 +163,10 @@ void TAMP_STAMP_LSECSS_IRQHandler(void) { if (LL_RCC_IsActiveFlag_LSECSS()) { LL_RCC_ClearFlag_LSECSS(); if (!LL_RCC_LSE_IsReady()) { - FURI_LOG_E("FuriHalInterrupt", "LSE CSS fired: resetting system"); + FURI_LOG_E(TAG, "LSE CSS fired: resetting system"); NVIC_SystemReset(); } else { - FURI_LOG_E("FuriHalInterrupt", "LSE CSS fired: but LSE is alive"); + FURI_LOG_E(TAG, "LSE CSS fired: but LSE is alive"); } } } @@ -176,7 +178,7 @@ void RCC_IRQHandler(void) { void NMI_Handler(void) { if (LL_RCC_IsActiveFlag_HSECSS()) { LL_RCC_ClearFlag_HSECSS(); - FURI_LOG_E("FuriHalInterrupt", "HSE CSS fired: resetting system"); + FURI_LOG_E(TAG, "HSE CSS fired: resetting system"); NVIC_SystemReset(); } } diff --git a/firmware/targets/f7/furi-hal/furi-hal-light.c b/firmware/targets/f7/furi-hal/furi-hal-light.c index fba1bec4..ecf0d4f2 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-light.c +++ b/firmware/targets/f7/furi-hal/furi-hal-light.c @@ -1,6 +1,8 @@ #include #include +#define TAG "FuriHalLight" + #define LED_CURRENT_RED 50 #define LED_CURRENT_GREEN 50 #define LED_CURRENT_BLUE 50 @@ -21,7 +23,7 @@ void furi_hal_light_init() { lp5562_enable(); lp5562_configure(); - FURI_LOG_I("FuriHalLight", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_light_set(Light light, uint8_t value) { diff --git a/firmware/targets/f7/furi-hal/furi-hal-nfc.c b/firmware/targets/f7/furi-hal/furi-hal-nfc.c index d92e2cad..4bca12a9 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-nfc.c +++ b/firmware/targets/f7/furi-hal/furi-hal-nfc.c @@ -1,15 +1,17 @@ #include "furi-hal-nfc.h" #include +#define TAG "FuriHalNfc" + static const uint32_t clocks_in_ms = 64 * 1000; void furi_hal_nfc_init() { ReturnCode ret = rfalNfcInitialize(); if(ret == ERR_NONE) { furi_hal_nfc_start_sleep(); - FURI_LOG_I("FuriHalNfc", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } else { - FURI_LOG_W("FuriHalNfc", "Initialization failed, RFAL returned: %d", ret); + FURI_LOG_W(TAG, "Initialization failed, RFAL returned: %d", ret); } } @@ -63,7 +65,7 @@ bool furi_hal_nfc_detect(rfalNfcDevice **dev_list, uint8_t* dev_cnt, uint32_t ti while(state != RFAL_NFC_STATE_ACTIVATED) { rfalNfcWorker(); state = rfalNfcGetState(); - FURI_LOG_D("HAL NFC", "Current state %d", state); + FURI_LOG_D(TAG, "Current state %d", state); if(state == RFAL_NFC_STATE_POLL_ACTIVATION) { start = DWT->CYCCNT; continue; @@ -73,7 +75,7 @@ bool furi_hal_nfc_detect(rfalNfcDevice **dev_list, uint8_t* dev_cnt, uint32_t ti } if(DWT->CYCCNT - start > timeout * clocks_in_ms) { rfalNfcDeactivate(true); - FURI_LOG_D("HAL NFC", "Timeout"); + FURI_LOG_D(TAG, "Timeout"); return false; } osThreadYield(); diff --git a/firmware/targets/f7/furi-hal/furi-hal-os.c b/firmware/targets/f7/furi-hal/furi-hal-os.c index eb1811b6..aac1b10e 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-os.c +++ b/firmware/targets/f7/furi-hal/furi-hal-os.c @@ -5,6 +5,8 @@ #include +#define TAG "FuriHalOs" + #define FURI_HAL_OS_CLK_FREQUENCY 32768 #define FURI_HAL_OS_TICK_PER_SECOND 1024 #define FURI_HAL_OS_CLK_PER_TICK (FURI_HAL_OS_CLK_FREQUENCY / FURI_HAL_OS_TICK_PER_SECOND) @@ -44,7 +46,7 @@ void furi_hal_os_init() { osTimerStart(second_timer, 1024); #endif - FURI_LOG_I("FuriHalOs", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void LPTIM2_IRQHandler(void) { diff --git a/firmware/targets/f7/furi-hal/furi-hal-power.c b/firmware/targets/f7/furi-hal/furi-hal-power.c index 47ce5f4d..870cbda6 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-power.c +++ b/firmware/targets/f7/furi-hal/furi-hal-power.c @@ -15,6 +15,8 @@ #include +#define TAG "FuriHalPower" + typedef struct { volatile uint8_t insomnia; volatile uint8_t deep_insomnia; @@ -74,7 +76,7 @@ void furi_hal_power_init() { LL_PWR_SMPS_SetMode(LL_PWR_SMPS_STEP_DOWN); bq27220_init(&cedv); bq25896_init(); - FURI_LOG_I("FuriHalPower", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } uint16_t furi_hal_power_insomnia_level() { diff --git a/firmware/targets/f7/furi-hal/furi-hal-rfid.c b/firmware/targets/f7/furi-hal/furi-hal-rfid.c index 59d24333..02a82bd1 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-rfid.c +++ b/firmware/targets/f7/furi-hal/furi-hal-rfid.c @@ -109,7 +109,7 @@ void furi_hal_rfid_tim_read(float freq, float duty_cycle) { sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; - if(HAL_TIM_OC_ConfigChannel(&LFRFID_READ_TIM, &sConfigOC, LFRFID_READ_CHANNEL) != HAL_OK) { + if(HAL_TIM_PWM_ConfigChannel(&LFRFID_READ_TIM, &sConfigOC, LFRFID_READ_CHANNEL) != HAL_OK) { Error_Handler(); } @@ -147,7 +147,6 @@ void furi_hal_rfid_tim_emulate(float freq) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; - TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; // basic PWM setup with needed freq and internal clock LFRFID_EMULATE_TIM.Init.Prescaler = 0; @@ -191,24 +190,6 @@ void furi_hal_rfid_tim_emulate(float freq) { HAL_OK) { Error_Handler(); } - - // no deadtime - sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; - sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; - sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; - sBreakDeadTimeConfig.DeadTime = 0; - sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; - sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; - sBreakDeadTimeConfig.BreakFilter = 0; - sBreakDeadTimeConfig.BreakAFMode = TIM_BREAK_AFMODE_INPUT; - sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE; - sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH; - sBreakDeadTimeConfig.Break2Filter = 0; - sBreakDeadTimeConfig.Break2AFMode = TIM_BREAK_AFMODE_INPUT; - sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; - if(HAL_TIMEx_ConfigBreakDeadTime(&LFRFID_EMULATE_TIM, &sBreakDeadTimeConfig) != HAL_OK) { - Error_Handler(); - } } void furi_hal_rfid_tim_emulate_start() { diff --git a/firmware/targets/f7/furi-hal/furi-hal-spi.c b/firmware/targets/f7/furi-hal/furi-hal-spi.c index 805b8dfb..da7c63df 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-spi.c +++ b/firmware/targets/f7/furi-hal/furi-hal-spi.c @@ -9,6 +9,8 @@ #include #include +#define TAG "FuriHalSpi" + void furi_hal_spi_init() { // Spi structure is const, but mutex is not // Need some hell-ish casting to make it work @@ -33,7 +35,7 @@ void furi_hal_spi_init() { hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); - FURI_LOG_I("FuriHalSpi", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) { diff --git a/firmware/targets/f7/furi-hal/furi-hal-subghz.c b/firmware/targets/f7/furi-hal/furi-hal-subghz.c index cd610cb2..276482ee 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-subghz.c +++ b/firmware/targets/f7/furi-hal/furi-hal-subghz.c @@ -10,6 +10,8 @@ #include #include +#define TAG "FuriHalSubGhz" + static volatile SubGhzState furi_hal_subghz_state = SubGhzStateInit; static volatile SubGhzRegulation furi_hal_subghz_regulation = SubGhzRegulationTxRx; @@ -303,7 +305,7 @@ void furi_hal_subghz_init() { cc1101_shutdown(device); furi_hal_spi_device_return(device); - FURI_LOG_I("FuriHalSubGhz", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_subghz_sleep() { diff --git a/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c b/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c index dd82cf16..e1f5de7d 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c +++ b/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c @@ -345,6 +345,7 @@ static const struct CdcConfigDescriptorDual cdc_cfg_desc_dual = { }; static struct usb_cdc_line_coding cdc_config[IF_NUM_MAX] = {}; +static uint8_t cdc_ctrl_line_state[IF_NUM_MAX]; static void cdc_init(usbd_device* dev, struct UsbInterface* intf); static void cdc_deinit(usbd_device *dev); @@ -438,6 +439,12 @@ struct usb_cdc_line_coding* furi_hal_cdc_get_port_settings(uint8_t if_num) { return NULL; } +uint8_t furi_hal_cdc_get_ctrl_line_state(uint8_t if_num) { + if (if_num < 2) + return cdc_ctrl_line_state[if_num]; + return 0; +} + void furi_hal_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len) { if (if_num == 0) usbd_ep_write(usb_dev, CDC0_TXD_EP, buf, len); @@ -465,6 +472,7 @@ static void cdc_on_wakeup(usbd_device *dev) { static void cdc_on_suspend(usbd_device *dev) { for (uint8_t i = 0; i < IF_NUM_MAX; i++) { + cdc_ctrl_line_state[i] = 0; if (callbacks[i] != NULL) { if (callbacks[i]->state_callback != NULL) callbacks[i]->state_callback(0); @@ -580,8 +588,9 @@ static usbd_respond cdc_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_cal switch(req->bRequest) { case USB_CDC_SET_CONTROL_LINE_STATE: if (callbacks[if_num] != NULL) { + cdc_ctrl_line_state[if_num] = req->wValue; if (callbacks[if_num]->ctrl_line_callback != NULL) - callbacks[if_num]->ctrl_line_callback(req->wValue); + callbacks[if_num]->ctrl_line_callback(cdc_ctrl_line_state[if_num]); } return usbd_ack; case USB_CDC_SET_LINE_CODING: diff --git a/firmware/targets/f7/furi-hal/furi-hal-usb-cdc_i.h b/firmware/targets/f7/furi-hal/furi-hal-usb-cdc_i.h index 3b181582..c4859e69 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-usb-cdc_i.h +++ b/firmware/targets/f7/furi-hal/furi-hal-usb-cdc_i.h @@ -17,6 +17,8 @@ void furi_hal_cdc_set_callbacks(uint8_t if_num, CdcCallbacks* cb); struct usb_cdc_line_coding* furi_hal_cdc_get_port_settings(uint8_t if_num); +uint8_t furi_hal_cdc_get_ctrl_line_state(uint8_t if_num); + void furi_hal_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len); int32_t furi_hal_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len); diff --git a/firmware/targets/f7/furi-hal/furi-hal-usb.c b/firmware/targets/f7/furi-hal/furi-hal-usb.c index 8c78eb8b..45a6177e 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-usb.c +++ b/firmware/targets/f7/furi-hal/furi-hal-usb.c @@ -5,6 +5,8 @@ #include "usb.h" +#define TAG "FuriHalUsb" + #define USB_RECONNECT_DELAY 500 extern struct UsbInterface usb_cdc_single; @@ -64,7 +66,7 @@ void furi_hal_usb_init(void) { HAL_NVIC_SetPriority(USB_LP_IRQn, 5, 0); NVIC_EnableIRQ(USB_LP_IRQn); - FURI_LOG_I("FuriHalUsb", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } void furi_hal_usb_set_config(UsbMode new_mode) { @@ -81,7 +83,7 @@ void furi_hal_usb_set_config(UsbMode new_mode) { usb_if_modes[usb_config.mode_cur]->deinit(&udev); if (usb_if_modes[new_mode] != NULL) { usb_if_modes[new_mode]->init(&udev, usb_if_modes[new_mode]); - FURI_LOG_I("FuriHalUsb", "USB mode change %u -> %u", usb_config.mode_cur, new_mode); + FURI_LOG_I(TAG, "USB mode change %u -> %u", usb_config.mode_cur, new_mode); usb_config.enabled = true; usb_config.mode_cur = new_mode; } @@ -98,7 +100,7 @@ void furi_hal_usb_disable() { susp_evt(&udev, 0, 0); usbd_connect(&udev, false); usb_config.enabled = false; - FURI_LOG_I("FuriHalUsb", "USB Disable"); + FURI_LOG_I(TAG, "USB Disable"); } } @@ -106,7 +108,7 @@ void furi_hal_usb_enable() { if ((!usb_config.enabled) && (usb_if_modes[usb_config.mode_cur] != NULL)) { usbd_connect(&udev, true); usb_config.enabled = true; - FURI_LOG_I("FuriHalUsb", "USB Enable"); + FURI_LOG_I(TAG, "USB Enable"); } } diff --git a/firmware/targets/f7/furi-hal/furi-hal-vcp.c b/firmware/targets/f7/furi-hal/furi-hal-vcp.c index b0b47f46..039481f1 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-vcp.c +++ b/firmware/targets/f7/furi-hal/furi-hal-vcp.c @@ -1,32 +1,42 @@ #include - +#include #include #include +#define TAG "FuriHalVcp" + #define USB_CDC_PKT_LEN CDC_DATA_SZ +#define VCP_RX_BUF_SIZE (USB_CDC_PKT_LEN * 3) +#define VCP_TX_BUF_SIZE (USB_CDC_PKT_LEN * 3) + #define VCP_IF_NUM 0 typedef enum { - VcpConnect, - VcpDisconnect, -} VcpEvent; + VcpEvtReserved = (1 << 0), // Reserved for StreamBuffer internal event + VcpEvtConnect = (1 << 1), + VcpEvtDisconnect = (1 << 2), + VcpEvtEnable = (1 << 3), + VcpEvtDisable = (1 << 4), + VcpEvtRx = (1 << 5), + VcpEvtTx = (1 << 6), + VcpEvtStreamRx = (1 << 7), + VcpEvtStreamTx = (1 << 8), +} WorkerEvtFlags; + +#define VCP_THREAD_FLAG_ALL (VcpEvtConnect | VcpEvtDisconnect | VcpEvtEnable | VcpEvtDisable | VcpEvtRx | VcpEvtTx | VcpEvtStreamRx | VcpEvtStreamTx) typedef struct { + FuriThread* thread; + + StreamBufferHandle_t tx_stream; + StreamBufferHandle_t rx_stream; + volatile bool connected; - uint8_t rx_buf[USB_CDC_PKT_LEN]; - uint8_t rx_buf_start; - uint8_t rx_buf_len; - - osMessageQueueId_t event_queue; - - osMutexId_t usb_mutex; - - osSemaphoreId_t tx_sem; - osSemaphoreId_t rx_sem; - + uint8_t data_buffer[USB_CDC_PKT_LEN]; } FuriHalVcp; +static int32_t vcp_worker(void* context); static void vcp_on_cdc_tx_complete(); static void vcp_on_cdc_rx(); static void vcp_state_callback(uint8_t state); @@ -49,34 +59,137 @@ void furi_hal_vcp_init() { vcp = furi_alloc(sizeof(FuriHalVcp)); vcp->connected = false; - vcp->usb_mutex = osMutexNew(NULL); + vcp->tx_stream = xStreamBufferCreate(VCP_TX_BUF_SIZE, 1); + vcp->rx_stream = xStreamBufferCreate(VCP_RX_BUF_SIZE, 1); - vcp->tx_sem = osSemaphoreNew(1, 1, NULL); - vcp->rx_sem = osSemaphoreNew(1, 0, NULL); + vcp->thread = furi_thread_alloc(); + furi_thread_set_name(vcp->thread, "VcpWorker"); + furi_thread_set_stack_size(vcp->thread, 1024); + furi_thread_set_callback(vcp->thread, vcp_worker); + furi_thread_start(vcp->thread); - vcp->event_queue = osMessageQueueNew(8, sizeof(VcpEvent), NULL); + FURI_LOG_I(TAG, "Init OK"); +} + +static int32_t vcp_worker(void* context) { + bool enabled = true; + bool tx_idle = false; + size_t missed_rx = 0; furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb); - FURI_LOG_I("FuriHalVcp", "Init OK"); + while (1) { + uint32_t flags = osThreadFlagsWait(VCP_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever); + furi_assert((flags & osFlagsError) == 0); + + // New data received + if((flags & VcpEvtStreamRx) && enabled && missed_rx > 0) { +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP StreamRx\r\n"); +#endif + if (xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) { + flags |= VcpEvtRx; + missed_rx--; + } + } + + // Rx buffer was read, maybe there is enough space for new data? + if((flags & VcpEvtRx)) { + if (xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) { + int32_t len = furi_hal_cdc_receive(VCP_IF_NUM, vcp->data_buffer, USB_CDC_PKT_LEN); +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_printf("VCP Rx %d\r\n", len); +#endif + if (len > 0) { + furi_check(xStreamBufferSend(vcp->rx_stream, vcp->data_buffer, len, osWaitForever) == len); + } + } else { +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP Rx missed\r\n"); +#endif + missed_rx++; + } + } + + // New data in Tx buffer + if((flags & VcpEvtStreamTx) && enabled) { +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP StreamTx\r\n"); +#endif + if (tx_idle) { + flags |= VcpEvtTx; + } + } + + // CDC write transfer done + if((flags & VcpEvtTx) && enabled) { + size_t len = xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0); +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_printf("VCP Tx %d\r\n", len); +#endif + if (len > 0) { // Some data left in Tx buffer. Sending it now + tx_idle = false; + furi_hal_cdc_send(VCP_IF_NUM, vcp->data_buffer, len); + } else { // There is nothing to send. Set flag to start next transfer instantly + tx_idle = true; + } + } + + // VCP session opened + if((flags & VcpEvtConnect) && enabled) { +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP Connect\r\n"); +#endif + if (vcp->connected == false) { + vcp->connected = true; + xStreamBufferSend(vcp->rx_stream, &ascii_soh, 1, osWaitForever); + } + } + + // VCP session closed + if((flags & VcpEvtDisconnect) && enabled) { +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP Disconnect\r\n"); +#endif + if (vcp->connected == true) { + vcp->connected = false; + xStreamBufferSend(vcp->rx_stream, &ascii_eot, 1, osWaitForever); + } + } + + // VCP enabled + if((flags & VcpEvtEnable) && !enabled){ +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP Enable\r\n"); +#endif + furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb); + enabled = true; + furi_hal_cdc_receive(VCP_IF_NUM, vcp->data_buffer, USB_CDC_PKT_LEN); // flush Rx buffer + if (furi_hal_cdc_get_ctrl_line_state(VCP_IF_NUM) & (1 << 0)) { + vcp->connected = true; + xStreamBufferSend(vcp->rx_stream, &ascii_soh, 1, osWaitForever); + } + } + + // VCP disabled + if((flags & VcpEvtDisable) && enabled) { +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP Disable\r\n"); +#endif + enabled = false; + vcp->connected = false; + xStreamBufferSend(vcp->rx_stream, &ascii_eot, 1, osWaitForever); + } + } + return 0; } void furi_hal_vcp_enable() { - furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb); - VcpEvent evt = VcpConnect; - osMessageQueuePut(vcp->event_queue, &evt, 0, 0); - vcp->connected = true; - osSemaphoreRelease(vcp->tx_sem); - osSemaphoreRelease(vcp->rx_sem); + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtEnable); } void furi_hal_vcp_disable() { - furi_hal_cdc_set_callbacks(VCP_IF_NUM, NULL); - VcpEvent evt = VcpDisconnect; - osMessageQueuePut(vcp->event_queue, &evt, 0, 0); - vcp->connected = false; - osSemaphoreRelease(vcp->tx_sem); - osSemaphoreRelease(vcp->rx_sem); + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisable); } size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeout) { @@ -85,47 +198,17 @@ size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeo size_t rx_cnt = 0; - VcpEvent evt = VcpDisconnect; + while (size > 0) { + size_t batch_size = size; + if (batch_size > VCP_RX_BUF_SIZE) + batch_size = VCP_RX_BUF_SIZE; - if (vcp->rx_buf_len > 0) { - size_t len = (vcp->rx_buf_len > size) ? (size) : (vcp->rx_buf_len); - memcpy(&buffer[rx_cnt], &vcp->rx_buf[vcp->rx_buf_start], len); - vcp->rx_buf_len -= len; - vcp->rx_buf_start += len; - rx_cnt += len; - } - - while (rx_cnt < size) { - if (osMessageQueueGet(vcp->event_queue, &evt, NULL, 0) == osOK) { - if (evt == VcpConnect) - buffer[rx_cnt] = ascii_soh; - else { - buffer[rx_cnt] = ascii_eot; - vcp->rx_buf_len = 0; - } - rx_cnt++; - return rx_cnt; - } - - if (osSemaphoreAcquire(vcp->rx_sem, timeout) == osErrorTimeout) - return rx_cnt; - - furi_check(osMutexAcquire(vcp->usb_mutex, osWaitForever) == osOK); - size_t len = furi_hal_cdc_receive(VCP_IF_NUM, vcp->rx_buf, USB_CDC_PKT_LEN); - furi_check(osMutexRelease(vcp->usb_mutex) == osOK); - - vcp->rx_buf_len = len; - vcp->rx_buf_start = 0; - - if (vcp->rx_buf_len > (size - rx_cnt)) { - len = size - rx_cnt; - memcpy(&buffer[rx_cnt], vcp->rx_buf, len); - vcp->rx_buf_len -= len; - vcp->rx_buf_start += len; - } else { - memcpy(&buffer[rx_cnt], vcp->rx_buf, vcp->rx_buf_len); - vcp->rx_buf_len = 0; - } + size_t len = xStreamBufferReceive(vcp->rx_stream, buffer, batch_size, timeout); + if (len == 0) + break; + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStreamRx); + size -= len; + buffer += len; rx_cnt += len; } return rx_cnt; @@ -133,26 +216,20 @@ size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeo size_t furi_hal_vcp_rx(uint8_t* buffer, size_t size) { furi_assert(vcp); - - return furi_hal_vcp_rx_with_timeout(buffer, size, portMAX_DELAY); + return furi_hal_vcp_rx_with_timeout(buffer, size, osWaitForever); } void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) { furi_assert(vcp); + furi_assert(buffer); - while (size > 0 && vcp->connected) { - furi_check(osSemaphoreAcquire(vcp->tx_sem, osWaitForever) == osOK); - if (!vcp->connected) - break; - + while (size > 0) { size_t batch_size = size; - if (batch_size > USB_CDC_PKT_LEN) { - batch_size = USB_CDC_PKT_LEN; - } + if (batch_size > VCP_TX_BUF_SIZE) + batch_size = VCP_TX_BUF_SIZE; - furi_check(osMutexAcquire(vcp->usb_mutex, osWaitForever) == osOK); - furi_hal_cdc_send(VCP_IF_NUM, (uint8_t*)buffer, batch_size); - furi_check(osMutexRelease(vcp->usb_mutex) == osOK); + xStreamBufferSend(vcp->tx_stream, buffer, batch_size, osWaitForever); + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStreamTx); size -= batch_size; buffer += batch_size; @@ -160,52 +237,38 @@ void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) { } static void vcp_state_callback(uint8_t state) { - if (state == 1) { - osSemaphoreRelease(vcp->rx_sem); - //osSemaphoreRelease(vcp->tx_sem); - } - else if (vcp->connected) { - vcp->connected = false; - osSemaphoreRelease(vcp->rx_sem); - VcpEvent evt = VcpDisconnect; - osMessageQueuePut(vcp->event_queue, &evt, 0, 0); - //osSemaphoreRelease(vcp->tx_sem); +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP State\r\n"); +#endif + if (state == 0) { + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect); } } static void vcp_on_cdc_control_line(uint8_t state) { // bit 0: DTR state, bit 1: RTS state - bool dtr = state & 0b1; - - if (dtr) { - if (!vcp->connected) { - vcp->connected = true; - VcpEvent evt = VcpConnect; - osMessageQueuePut(vcp->event_queue, &evt, 0, 0); - } + bool dtr = state & (1 << 0); +#ifdef FURI_HAL_USB_VCP_DEBUG + furi_hal_console_puts("VCP CtrlLine\r\n"); +#endif + if (dtr == true) { + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtConnect); } else { - if (vcp->connected) { - VcpEvent evt = VcpDisconnect; - osMessageQueuePut(vcp->event_queue, &evt, 0, 0); - vcp->connected = false; - } + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect); } - - osSemaphoreRelease(vcp->tx_sem); - osSemaphoreRelease(vcp->rx_sem); } static void vcp_on_cdc_rx() { - if (vcp->connected == false) - return; - osSemaphoreRelease(vcp->rx_sem); + uint32_t ret = osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtRx); + furi_assert((ret & osFlagsError) == 0); } static void vcp_on_cdc_tx_complete() { - osSemaphoreRelease(vcp->tx_sem); + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtTx); } bool furi_hal_vcp_is_connected(void) { + furi_assert(vcp); return vcp->connected; } diff --git a/firmware/targets/f7/furi-hal/furi-hal-version.c b/firmware/targets/f7/furi-hal/furi-hal-version.c index e4adebc0..f38e6cdc 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-version.c +++ b/firmware/targets/f7/furi-hal/furi-hal-version.c @@ -7,6 +7,8 @@ #include #include "ble.h" +#define TAG "FuriHalVersion" + #define FURI_HAL_VERSION_OTP_HEADER_MAGIC 0xBABE #define FURI_HAL_VERSION_OTP_ADDRESS OTP_AREA_BASE @@ -191,7 +193,7 @@ void furi_hal_version_init() { break; default: furi_crash(NULL); } - FURI_LOG_I("FuriHalVersion", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } bool furi_hal_version_do_i_belong_here() { diff --git a/firmware/targets/f7/furi-hal/furi-hal-vibro.c b/firmware/targets/f7/furi-hal/furi-hal-vibro.c index 7dfddd42..7de8ad84 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-vibro.c +++ b/firmware/targets/f7/furi-hal/furi-hal-vibro.c @@ -1,10 +1,12 @@ #include #include +#define TAG "FuriHalVibro" + void furi_hal_vibro_init() { hal_gpio_init(&vibro_gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); hal_gpio_write(&vibro_gpio, false); - FURI_LOG_I("FuriHalVibro", "Init OK"); + FURI_LOG_I(TAG, "Init OK"); } diff --git a/firmware/targets/f7/furi-hal/furi-hal.c b/firmware/targets/f7/furi-hal/furi-hal.c index aa7536ef..d435c5f2 100644 --- a/firmware/targets/f7/furi-hal/furi-hal.c +++ b/firmware/targets/f7/furi-hal/furi-hal.c @@ -5,6 +5,12 @@ #include #include +#include + +#include + +#define TAG "FuriHal" + void furi_hal_init() { furi_hal_clock_init(); furi_hal_console_init(); @@ -12,23 +18,23 @@ void furi_hal_init() { furi_hal_delay_init(); MX_GPIO_Init(); - FURI_LOG_I("HAL", "GPIO OK"); + FURI_LOG_I(TAG, "GPIO OK"); MX_RTC_Init(); - FURI_LOG_I("HAL", "RTC OK"); + FURI_LOG_I(TAG, "RTC OK"); furi_hal_bootloader_init(); furi_hal_version_init(); furi_hal_spi_init(); MX_TIM1_Init(); - FURI_LOG_I("HAL", "TIM1 OK"); + FURI_LOG_I(TAG, "TIM1 OK"); MX_TIM2_Init(); - FURI_LOG_I("HAL", "TIM2 OK"); + FURI_LOG_I(TAG, "TIM2 OK"); MX_TIM16_Init(); - FURI_LOG_I("HAL", "TIM16 OK"); + FURI_LOG_I(TAG, "TIM16 OK"); MX_COMP1_Init(); - FURI_LOG_I("HAL", "COMP1 OK"); + FURI_LOG_I(TAG, "COMP1 OK"); furi_hal_crypto_init(); @@ -36,7 +42,7 @@ void furi_hal_init() { furi_hal_usb_init(); furi_hal_usb_set_config(UsbModeVcpSingle); furi_hal_vcp_init(); - FURI_LOG_I("HAL", "USB OK"); + FURI_LOG_I(TAG, "USB OK"); furi_hal_i2c_init(); @@ -52,4 +58,22 @@ void furi_hal_init() { // FreeRTOS glue furi_hal_os_init(); + + // FatFS driver initialization + MX_FATFS_Init(); + FURI_LOG_I(TAG, "FATFS OK"); + + // Partial null pointer dereference protection + LL_MPU_Disable(); + LL_MPU_ConfigRegion( + LL_MPU_REGION_NUMBER0, 0x00, 0x0, + LL_MPU_REGION_SIZE_1MB + | LL_MPU_REGION_PRIV_RO_URO + | LL_MPU_ACCESS_BUFFERABLE + | LL_MPU_ACCESS_CACHEABLE + | LL_MPU_ACCESS_SHAREABLE + | LL_MPU_TEX_LEVEL1 + | LL_MPU_INSTRUCTION_ACCESS_ENABLE + ); + LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT); } diff --git a/firmware/targets/f7/target.mk b/firmware/targets/f7/target.mk index 184bb9d2..d6b8cbfa 100644 --- a/firmware/targets/f7/target.mk +++ b/firmware/targets/f7/target.mk @@ -49,8 +49,6 @@ C_SOURCES += \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_cortex.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_cryp.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_exti.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash_ex.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_gpio.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_hsem.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_ipcc.c \ @@ -130,6 +128,11 @@ ifeq ($(FURI_HAL_OS_DEBUG), 1) CFLAGS += -DFURI_HAL_OS_DEBUG endif +FURI_HAL_USB_VCP_DEBUG ?= 0 +ifeq ($(FURI_HAL_USB_VCP_DEBUG), 1) +CFLAGS += -DFURI_HAL_USB_VCP_DEBUG +endif + FURI_HAL_SUBGHZ_TX_GPIO ?= 0 ifneq ($(FURI_HAL_SUBGHZ_TX_GPIO), 0) CFLAGS += -DFURI_HAL_SUBGHZ_TX_GPIO=$(FURI_HAL_SUBGHZ_TX_GPIO) @@ -146,10 +149,10 @@ C_SOURCES += $(wildcard $(FURI_HAL_DIR)/*.c) # Other CFLAGS += \ -I$(MXPROJECT_DIR)/Inc \ - -I$(MXPROJECT_DIR)/Src/fatfs + -I$(MXPROJECT_DIR)/fatfs C_SOURCES += \ $(wildcard $(MXPROJECT_DIR)/Src/*.c) \ - $(wildcard $(MXPROJECT_DIR)/Src/fatfs/*.c) + $(wildcard $(MXPROJECT_DIR)/fatfs/*.c) # Linker options ifeq ($(NO_BOOTLOADER), 1) diff --git a/firmware/targets/furi-hal-include/furi-hal-bt.h b/firmware/targets/furi-hal-include/furi-hal-bt.h index 461fc4ce..c7d86165 100644 --- a/firmware/targets/furi-hal-include/furi-hal-bt.h +++ b/firmware/targets/furi-hal-include/furi-hal-bt.h @@ -23,6 +23,12 @@ extern "C" { */ void furi_hal_bt_init(); +/** Lock core2 state transition */ +void furi_hal_bt_lock_core2(); + +/** Lock core2 state transition */ +void furi_hal_bt_unlock_core2(); + /** Start 2nd core and BLE stack * * @return true on success @@ -63,12 +69,10 @@ bool furi_hal_bt_is_alive(); /** Get key storage buffer address and size * - * @param key_buff_addr pointer to store buffer address - * @param key_buff_size pointer to store buffer size - * - * @return true on success + * @param key_buff_addr pointer to store buffer address + * @param key_buff_size pointer to store buffer size */ -bool furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size); +void furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size); /** Get SRAM2 hardware semaphore * @note Must be called before SRAM2 read/write operations @@ -92,7 +96,10 @@ void furi_hal_bt_set_key_storage_change_callback(BleGlueKeyStorageChangedCallbac * @param on_sent_cb - SerialSvcDataSentCallback instance * @param context - pointer to context */ -void furi_hal_bt_set_data_event_callbacks(SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context); +void furi_hal_bt_set_data_event_callbacks(uint16_t buff_size, SerialSvcDataReceivedCallback on_received_cb, SerialSvcDataSentCallback on_sent_cb, void* context); + +/** Notify that buffer is empty */ +void furi_hal_bt_notify_buffer_is_empty(); /** Send data through BLE * @param data - data buffer @@ -100,18 +107,6 @@ void furi_hal_bt_set_data_event_callbacks(SerialSvcDataReceivedCallback on_recei */ bool furi_hal_bt_tx(uint8_t* data, uint16_t size); -/** Lock shared access to flash controller - * - * @param[in] erase_flag true if erase operation - */ -void furi_hal_bt_lock_flash(bool erase_flag); - -/** Unlock shared access to flash controller - * - * @param[in] erase_flag true if erase operation - */ -void furi_hal_bt_unlock_flash(bool erase_flag); - /** Start ble tone tx at given channel and power * * @param[in] channel The channel diff --git a/lib/ST25RFAL002/platform.c b/lib/ST25RFAL002/platform.c index 7a011965..58363cac 100644 --- a/lib/ST25RFAL002/platform.c +++ b/lib/ST25RFAL002/platform.c @@ -38,7 +38,7 @@ void platformDisableIrqCallback() { void platformSetIrqCallback(PlatformIrqCallback callback) { platform_irq_callback = callback; - platform_irq_thread_attr.name = "rfal_irq_worker"; + platform_irq_thread_attr.name = "RfalIrqWorker"; platform_irq_thread_attr.stack_size = 1024; platform_irq_thread_attr.priority = osPriorityISR; platform_irq_thread_id = osThreadNew(platformIrqWorker, NULL, &platform_irq_thread_attr); diff --git a/lib/drivers/bq27220.c b/lib/drivers/bq27220.c index d83cae05..578e3849 100644 --- a/lib/drivers/bq27220.c +++ b/lib/drivers/bq27220.c @@ -5,6 +5,8 @@ #include #include +#define TAG "Gauge" + uint16_t bq27220_read_word(uint8_t address) { uint8_t buffer[2] = {address}; uint16_t ret; @@ -70,13 +72,13 @@ bool bq27220_init(const ParamCEDV* cedv) { uint32_t timeout = 100; uint16_t design_cap = bq27220_get_design_capacity(); if(cedv->design_cap == design_cap) { - FURI_LOG_I("gauge", "Skip battery profile update"); + FURI_LOG_I(TAG, "Skip battery profile update"); return true; } - FURI_LOG_I("gauge", "Start updating battery profile"); + FURI_LOG_I(TAG, "Start updating battery profile"); OperationStatus status = {}; if(!bq27220_control(Control_ENTER_CFG_UPDATE)) { - FURI_LOG_E("gauge", "Can't configure update"); + FURI_LOG_E(TAG, "Can't configure update"); return false; }; @@ -111,10 +113,10 @@ bool bq27220_init(const ParamCEDV* cedv) { delay_us(10000); design_cap = bq27220_get_design_capacity(); if(cedv->design_cap == design_cap) { - FURI_LOG_I("gauge", "Battery profile update success"); + FURI_LOG_I(TAG, "Battery profile update success"); return true; } else { - FURI_LOG_E("gauge", "Battery profile update failed"); + FURI_LOG_E(TAG, "Battery profile update failed"); return false; } } diff --git a/lib/irda/worker/irda_worker.c b/lib/irda/worker/irda_worker.c index 58b6ef5a..b9324334 100644 --- a/lib/irda/worker/irda_worker.c +++ b/lib/irda/worker/irda_worker.c @@ -216,7 +216,7 @@ IrdaWorker* irda_worker_alloc() { IrdaWorker* instance = furi_alloc(sizeof(IrdaWorker)); instance->thread = furi_thread_alloc(); - furi_thread_set_name(instance->thread, "irda_worker"); + furi_thread_set_name(instance->thread, "IrdaWorker"); furi_thread_set_stack_size(instance->thread, 2048); furi_thread_set_context(instance->thread, instance); diff --git a/lib/subghz/protocols/subghz_protocol_came.c b/lib/subghz/protocols/subghz_protocol_came.c index 866e577b..47597775 100644 --- a/lib/subghz/protocols/subghz_protocol_came.c +++ b/lib/subghz/protocols/subghz_protocol_came.c @@ -28,8 +28,8 @@ SubGhzProtocolCame* subghz_protocol_came_alloc() { instance->common.te_delta = 150; instance->common.type_protocol = SubGhzProtocolCommonTypeStatic; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_came_to_str; - instance->common.to_save_string = - (SubGhzProtocolCommonGetStrSave)subghz_protocol_came_to_save_str; + instance->common.to_save_file = + (SubGhzProtocolCommonSaveFile)subghz_protocol_came_to_save_file; instance->common.to_load_protocol_from_file = (SubGhzProtocolCommonLoadFromFile)subghz_protocol_came_to_load_protocol_from_file; instance->common.to_load_protocol = @@ -88,8 +88,6 @@ void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32 instance->common.te_delta * 51)) { //Need protocol 36 te_short //Found header CAME instance->common.parser_step = CameDecoderStepFoundStartBit; - } else { - instance->common.parser_step = CameDecoderStepReset; } break; case CameDecoderStepFoundStartBit: @@ -169,55 +167,16 @@ void subghz_protocol_came_to_str(SubGhzProtocolCame* instance, string_t output) code_found_reverse_lo); } -void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t output) { - string_printf( - output, - "Protocol: %s\n" - "Bit: %d\n" - "Key: %08lX\n", - instance->common.name, - instance->common.code_last_count_bit, - (uint32_t)(instance->common.code_last_found & 0x00000000ffffffff)); +bool subghz_protocol_came_to_save_file(SubGhzProtocolCame* instance, FlipperFile* flipper_file) { + return subghz_protocol_common_to_save_file((SubGhzProtocolCommon*)instance, flipper_file); } bool subghz_protocol_came_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolCame* instance, const char* file_path) { - bool loaded = false; - string_t temp_str; - string_init(temp_str); - int res = 0; - int data = 0; - - do { - // Read and parse bit data from 2nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data); - if(res != 1) { - break; - } - instance->common.code_last_count_bit = (uint8_t)data; - - // Read and parse key data from 3nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - uint32_t temp_key = 0; - res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key); - if(res != 1) { - break; - } - instance->common.code_last_found = (uint64_t)temp_key; - - loaded = true; - } while(0); - - string_clear(temp_str); - - return loaded; + return subghz_protocol_common_to_load_protocol_from_file( + (SubGhzProtocolCommon*)instance, flipper_file); } void subghz_decoder_came_to_load_protocol(SubGhzProtocolCame* instance, void* context) { diff --git a/lib/subghz/protocols/subghz_protocol_came.h b/lib/subghz/protocols/subghz_protocol_came.h index 603ca21a..22805c6b 100644 --- a/lib/subghz/protocols/subghz_protocol_came.h +++ b/lib/subghz/protocols/subghz_protocol_came.h @@ -45,22 +45,23 @@ void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32 */ void subghz_protocol_came_to_str(SubGhzProtocolCame* instance, string_t output); -/** Get a string to save the protocol +/** Adding data to a file * * @param instance - SubGhzProtocolCame instance - * @param output - the resulting string + * @param flipper_file - FlipperFile + * @return bool */ -void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t output); +bool subghz_protocol_came_to_save_file(SubGhzProtocolCame* instance, FlipperFile* flipper_file); /** Loading protocol from file * - * @param file_worker - FileWorker file_worker + * @param flipper_file - FlipperFile * @param instance - SubGhzProtocolCame instance * @param file_path - file path * @return bool */ bool subghz_protocol_came_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolCame* instance, const char* file_path); diff --git a/lib/subghz/protocols/subghz_protocol_came_atomo.c b/lib/subghz/protocols/subghz_protocol_came_atomo.c index 2f2bd071..fbf9ca38 100644 --- a/lib/subghz/protocols/subghz_protocol_came_atomo.c +++ b/lib/subghz/protocols/subghz_protocol_came_atomo.c @@ -3,6 +3,8 @@ #include #include "../subghz_keystore.h" +#define TAG "SubGhzCameAtomo" + #define SUBGHZ_NO_CAME_ATOMO_RAINBOW_TABLE 0xFFFFFFFFFFFFFFFF struct SubGhzProtocolCameAtomo { @@ -39,7 +41,7 @@ void subghz_protocol_came_atomo_free(SubGhzProtocolCameAtomo* instance) { void subghz_protocol_came_atomo_name_file(SubGhzProtocolCameAtomo* instance, const char* name) { instance->rainbow_table_file_name = name; - printf("Loading CAME Atomo rainbow table %s\r\n", name); + FURI_LOG_I(TAG, "Loading rainbow table from %s", name); } /** Read bytes from rainbow table @@ -177,8 +179,6 @@ void subghz_protocol_came_atomo_parse( ManchesterEventShortLow, &instance->manchester_saved_state, NULL); - } else { - instance->common.parser_step = CameAtomoDecoderStepReset; } break; case CameAtomoDecoderStepDecoderData: diff --git a/lib/subghz/protocols/subghz_protocol_came_twee.c b/lib/subghz/protocols/subghz_protocol_came_twee.c index 8e527c8f..54416902 100644 --- a/lib/subghz/protocols/subghz_protocol_came_twee.c +++ b/lib/subghz/protocols/subghz_protocol_came_twee.c @@ -36,8 +36,8 @@ SubGhzProtocolCameTwee* subghz_protocol_came_twee_alloc() { instance->common.te_delta = 250; instance->common.type_protocol = SubGhzProtocolCommonTypeStatic; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_came_twee_to_str; - instance->common.to_save_string = - (SubGhzProtocolCommonGetStrSave)subghz_protocol_came_twee_to_save_str; + instance->common.to_save_file = + (SubGhzProtocolCommonSaveFile)subghz_protocol_came_twee_to_save_file; instance->common.to_load_protocol_from_file = (SubGhzProtocolCommonLoadFromFile)subghz_protocol_came_twee_to_load_protocol_from_file; instance->common.to_load_protocol = @@ -247,8 +247,6 @@ void subghz_protocol_came_twee_parse( ManchesterEventShortLow, &instance->manchester_saved_state, NULL); - } else { - instance->common.parser_step = CameTweeDecoderStepReset; } break; case CameTweeDecoderStepDecoderData: @@ -327,62 +325,22 @@ void subghz_protocol_came_twee_to_str(SubGhzProtocolCameTwee* instance, string_t CNT_TO_DIP(instance->common.cnt)); } -void subghz_protocol_came_twee_to_save_str(SubGhzProtocolCameTwee* instance, string_t output) { - string_printf( - output, - "Protocol: %s\n" - "Bit: %d\n" - "Key: %08lX%08lX\r\n", - instance->common.name, - instance->common.code_last_count_bit, - (uint32_t)(instance->common.code_last_found >> 32), - (uint32_t)(instance->common.code_last_found & 0xFFFFFFFF)); +bool subghz_protocol_came_twee_to_save_file( + SubGhzProtocolCameTwee* instance, + FlipperFile* flipper_file) { + return subghz_protocol_common_to_save_file((SubGhzProtocolCommon*)instance, flipper_file); } bool subghz_protocol_came_twee_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolCameTwee* instance, const char* file_path) { - bool loaded = false; - string_t temp_str; - string_init(temp_str); - int res = 0; - int data = 0; - - do { - // Read and parse bit data from 2nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data); - if(res != 1) { - break; - } - instance->common.code_last_count_bit = (uint8_t)data; - - // Read and parse key data from 3nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - // strlen("Key: ") = 5 - string_right(temp_str, 5); - - uint8_t buf_key[8] = {0}; - if(!subghz_protocol_common_read_hex(temp_str, buf_key, 8)) { - break; - } - - for(uint8_t i = 0; i < 8; i++) { - instance->common.code_last_found = instance->common.code_last_found << 8 | buf_key[i]; - } - - loaded = true; - } while(0); - - string_clear(temp_str); - - subghz_protocol_came_twee_remote_controller(instance); - return loaded; + if(subghz_protocol_common_to_load_protocol_from_file( + (SubGhzProtocolCommon*)instance, flipper_file)) { + subghz_protocol_came_twee_remote_controller(instance); + return true; + } + return false; } void subghz_decoder_came_twee_to_load_protocol(SubGhzProtocolCameTwee* instance, void* context) { diff --git a/lib/subghz/protocols/subghz_protocol_came_twee.h b/lib/subghz/protocols/subghz_protocol_came_twee.h index c8f3d465..32e17eff 100644 --- a/lib/subghz/protocols/subghz_protocol_came_twee.h +++ b/lib/subghz/protocols/subghz_protocol_came_twee.h @@ -48,22 +48,25 @@ void subghz_protocol_came_twee_parse( */ void subghz_protocol_came_twee_to_str(SubGhzProtocolCameTwee* instance, string_t output); -/** Get a string to save the protocol +/** Adding data to a file * * @param instance - SubGhzProtocolCameTwee instance - * @param output - the resulting string + * @param flipper_file - FlipperFile + * @return bool */ -void subghz_protocol_came_twee_to_save_str(SubGhzProtocolCameTwee* instance, string_t output); +bool subghz_protocol_came_twee_to_save_file( + SubGhzProtocolCameTwee* instance, + FlipperFile* flipper_file); /** Loading protocol from file * - * @param file_worker - FileWorker file_worker + * @param flipper_file - FlipperFile * @param instance - SubGhzProtocolCameTwee instance * @param file_path - file path * @return bool */ bool subghz_protocol_came_twee_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolCameTwee* instance, const char* file_path); diff --git a/lib/subghz/protocols/subghz_protocol_common.c b/lib/subghz/protocols/subghz_protocol_common.c index be1fea94..95ca876f 100644 --- a/lib/subghz/protocols/subghz_protocol_common.c +++ b/lib/subghz/protocols/subghz_protocol_common.c @@ -168,3 +168,67 @@ bool subghz_protocol_common_read_hex(string_t str, uint8_t* buff, uint16_t len) } return parsed; } + +bool subghz_protocol_common_to_save_file(SubGhzProtocolCommon* instance, FlipperFile* flipper_file) { + furi_assert(instance); + furi_assert(flipper_file); + bool res = false; + do { + if(!flipper_file_write_string_cstr(flipper_file, "Protocol", instance->name)) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unable to add Protocol"); + break; + } + if(!flipper_file_write_uint32( + flipper_file, "Bit", (uint32_t*)&instance->code_last_count_bit, 1)) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unable to add Bit"); + break; + } + + uint8_t key_data[sizeof(uint64_t)] = {0}; + for(size_t i = 0; i < sizeof(uint64_t); i++) { + key_data[sizeof(uint64_t) - i - 1] = (instance->code_last_found >> i * 8) & 0xFF; + } + + if(!flipper_file_write_hex(flipper_file, "Key", key_data, sizeof(uint64_t))) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unable to add Key"); + break; + } + res = true; + } while(false); + + return res; +} + +bool subghz_protocol_common_to_load_protocol_from_file( + SubGhzProtocolCommon* instance, + FlipperFile* flipper_file) { + furi_assert(instance); + furi_assert(flipper_file); + bool loaded = false; + string_t temp_str; + string_init(temp_str); + uint32_t temp_data = 0; + + do { + if(!flipper_file_read_uint32(flipper_file, "Bit", (uint32_t*)&temp_data, 1)) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Missing Bit"); + break; + } + instance->code_last_count_bit = (uint8_t)temp_data; + + uint8_t key_data[sizeof(uint64_t)] = {0}; + if(!flipper_file_read_hex(flipper_file, "Key", key_data, sizeof(uint64_t))) { + FURI_LOG_E(SUBGHZ_PARSER_TAG, "Missing Key"); + break; + } + for(uint8_t i = 0; i < sizeof(uint64_t); i++) { + instance->code_last_found = instance->code_last_found << 8 | key_data[i]; + } + + loaded = true; + } while(0); + + string_clear(temp_str); + + return loaded; +} diff --git a/lib/subghz/protocols/subghz_protocol_common.h b/lib/subghz/protocols/subghz_protocol_common.h index 4d53dfe2..6064f895 100644 --- a/lib/subghz/protocols/subghz_protocol_common.h +++ b/lib/subghz/protocols/subghz_protocol_common.h @@ -3,7 +3,7 @@ #include #include #include -#include "file-worker.h" +#include #define bit_read(value, bit) (((value) >> (bit)) & 0x01) #define bit_set(value, bit) ((value) |= (1UL << (bit))) @@ -21,6 +21,14 @@ #define SUBGHZ_APP_EXTENSION ".sub" #define SUBGHZ_ENCODER_UPLOAD_MAX_SIZE 2048 +#define SUBGHZ_PARSER_TAG "SubGhzParser" +#define SUBGHZ_KEY_FILE_VERSION 1 +#define SUBGHZ_KEY_FILE_TYPE "Flipper SubGhz Key File" + +#define SUBGHZ_RAW_FILE_VERSION 1 +#define SUBGHZ_RAW_FILE_TYPE "Flipper SubGhz RAW File" + + typedef enum { SubGhzProtocolCommonTypeUnknown, SubGhzProtocolCommonTypeStatic, @@ -37,11 +45,14 @@ typedef void (*SubGhzProtocolCommonCallback)(SubGhzProtocolCommon* parser, void* typedef void (*SubGhzProtocolCommonToStr)(SubGhzProtocolCommon* instance, string_t output); //Get string to save -typedef void (*SubGhzProtocolCommonGetStrSave)(SubGhzProtocolCommon* instance, string_t output); +typedef bool ( + *SubGhzProtocolCommonSaveFile)(SubGhzProtocolCommon* instance, FlipperFile* flipper_file); //Load protocol from file -typedef bool ( - *SubGhzProtocolCommonLoadFromFile)(FileWorker* file_worker, SubGhzProtocolCommon* instance, const char* file_path); +typedef bool (*SubGhzProtocolCommonLoadFromFile)( + FlipperFile* flipper_file, + SubGhzProtocolCommon* instance, + const char* file_path); //Load protocol typedef void (*SubGhzProtocolCommonLoadFromRAW)(SubGhzProtocolCommon* instance, void* context); //Get upload encoder protocol @@ -77,7 +88,7 @@ struct SubGhzProtocolCommon { /* Dump To String */ SubGhzProtocolCommonToStr to_string; /* Get string to save */ - SubGhzProtocolCommonGetStrSave to_save_string; + SubGhzProtocolCommonSaveFile to_save_file; /* Load protocol from file */ SubGhzProtocolCommonLoadFromFile to_load_protocol_from_file; /* Load protocol from RAW data */ @@ -196,3 +207,21 @@ void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t outp * @return bool */ bool subghz_protocol_common_read_hex(string_t str, uint8_t* buff, uint16_t len); + +/** Adding data to a file + * + * @param instance - SubGhzProtocolCommon instance + * @param flipper_file - FlipperFile + * @return bool + */ +bool subghz_protocol_common_to_save_file(SubGhzProtocolCommon* instance, FlipperFile* flipper_file); + +/** Loading data to a file + * + * @param instance - SubGhzProtocolCommon instance + * @param flipper_file - FlipperFile + * @return bool + */ +bool subghz_protocol_common_to_load_protocol_from_file( + SubGhzProtocolCommon* instance, + FlipperFile* flipper_file); diff --git a/lib/subghz/protocols/subghz_protocol_faac_slh.c b/lib/subghz/protocols/subghz_protocol_faac_slh.c index a6ee72ed..5bce4f8d 100644 --- a/lib/subghz/protocols/subghz_protocol_faac_slh.c +++ b/lib/subghz/protocols/subghz_protocol_faac_slh.c @@ -95,8 +95,6 @@ void subghz_protocol_faac_slh_parse(SubGhzProtocolFaacSLH* instance, bool level, if((level) && (DURATION_DIFF(duration, instance->common.te_long * 2) < instance->common.te_delta * 3)) { instance->common.parser_step = FaacSLHDecoderStepFoundPreambula; - } else { - instance->common.parser_step = FaacSLHDecoderStepReset; } break; case FaacSLHDecoderStepFoundPreambula: diff --git a/lib/subghz/protocols/subghz_protocol_gate_tx.c b/lib/subghz/protocols/subghz_protocol_gate_tx.c index ea2f7aeb..05e8c151 100644 --- a/lib/subghz/protocols/subghz_protocol_gate_tx.c +++ b/lib/subghz/protocols/subghz_protocol_gate_tx.c @@ -21,8 +21,8 @@ SubGhzProtocolGateTX* subghz_protocol_gate_tx_alloc(void) { instance->common.te_delta = 100; instance->common.type_protocol = SubGhzProtocolCommonTypeStatic; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_gate_tx_to_str; - instance->common.to_save_string = - (SubGhzProtocolCommonGetStrSave)subghz_protocol_gate_tx_to_save_str; + instance->common.to_save_file = + (SubGhzProtocolCommonSaveFile)subghz_protocol_gate_tx_to_save_file; instance->common.to_load_protocol_from_file = (SubGhzProtocolCommonLoadFromFile)subghz_protocol_gate_tx_to_load_protocol_from_file; instance->common.to_load_protocol = @@ -94,8 +94,6 @@ void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, u instance->common.te_delta * 47)) { //Found Preambula instance->common.parser_step = GateTXDecoderStepFoundStartBit; - } else { - instance->common.parser_step = GateTXDecoderStepReset; } break; case GateTXDecoderStepFoundStartBit: @@ -169,56 +167,22 @@ void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t out instance->common.btn); } -void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_t output) { - string_printf( - output, - "Protocol: %s\n" - "Bit: %d\n" - "Key: %08lX\n", - instance->common.name, - instance->common.code_last_count_bit, - (uint32_t)(instance->common.code_last_found & 0x00000000ffffffff)); +bool subghz_protocol_gate_tx_to_save_file( + SubGhzProtocolGateTX* instance, + FlipperFile* flipper_file) { + return subghz_protocol_common_to_save_file((SubGhzProtocolCommon*)instance, flipper_file); } bool subghz_protocol_gate_tx_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolGateTX* instance, const char* file_path) { - bool loaded = false; - string_t temp_str; - string_init(temp_str); - int res = 0; - int data = 0; - - do { - // Read and parse bit data from 2nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data); - if(res != 1) { - break; - } - instance->common.code_last_count_bit = (uint8_t)data; - - // Read and parse key data from 3nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - uint32_t temp_key = 0; - res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key); - if(res != 1) { - break; - } - instance->common.code_last_found = (uint64_t)temp_key; + if(subghz_protocol_common_to_load_protocol_from_file( + (SubGhzProtocolCommon*)instance, flipper_file)) { subghz_protocol_gate_tx_check_remote_controller(instance); - - loaded = true; - } while(0); - - string_clear(temp_str); - - return loaded; + return true; + } + return false; } void subghz_decoder_gate_tx_to_load_protocol(SubGhzProtocolGateTX* instance, void* context) { diff --git a/lib/subghz/protocols/subghz_protocol_gate_tx.h b/lib/subghz/protocols/subghz_protocol_gate_tx.h index 57ca5832..5954f6ca 100644 --- a/lib/subghz/protocols/subghz_protocol_gate_tx.h +++ b/lib/subghz/protocols/subghz_protocol_gate_tx.h @@ -45,22 +45,25 @@ void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, u */ void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t output); -/** Get a string to save the protocol +/** Adding data to a file * * @param instance - SubGhzProtocolGateTX instance - * @param output - the resulting string + * @param flipper_file - FlipperFile + * @return bool */ -void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_t output); +bool subghz_protocol_gate_tx_to_save_file( + SubGhzProtocolGateTX* instance, + FlipperFile* flipper_file); /** Loading protocol from file * - * @param file_worker - FileWorker file_worker + * @param flipper_file - FlipperFile * @param instance - SubGhzProtocolGateTX instance * @param file_path - file path * @return bool */ bool subghz_protocol_gate_tx_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolGateTX* instance, const char* file_path); diff --git a/lib/subghz/protocols/subghz_protocol_hormann.c b/lib/subghz/protocols/subghz_protocol_hormann.c index 0d4df921..4b6a8094 100644 --- a/lib/subghz/protocols/subghz_protocol_hormann.c +++ b/lib/subghz/protocols/subghz_protocol_hormann.c @@ -24,8 +24,8 @@ SubGhzProtocolHormann* subghz_protocol_hormann_alloc() { instance->common.te_delta = 200; instance->common.type_protocol = SubGhzProtocolCommonTypeStatic; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_hormann_to_str; - instance->common.to_save_string = - (SubGhzProtocolCommonGetStrSave)subghz_protocol_hormann_to_save_str; + instance->common.to_save_file = + (SubGhzProtocolCommonSaveFile)subghz_protocol_hormann_to_save_file; instance->common.to_load_protocol_from_file = (SubGhzProtocolCommonLoadFromFile)subghz_protocol_hormann_to_load_protocol_from_file; instance->common.to_load_protocol = @@ -94,8 +94,6 @@ void subghz_protocol_hormann_parse(SubGhzProtocolHormann* instance, bool level, if((level) && (DURATION_DIFF(duration, instance->common.te_short * 64) < instance->common.te_delta * 64)) { instance->common.parser_step = HormannDecoderStepFoundStartHeader; - } else { - instance->common.parser_step = HormannDecoderStepReset; } break; case HormannDecoderStepFoundStartHeader: @@ -188,61 +186,18 @@ void subghz_protocol_hormann_to_str(SubGhzProtocolHormann* instance, string_t ou instance->common.btn); } -void subghz_protocol_hormann_to_save_str(SubGhzProtocolHormann* instance, string_t output) { - string_printf( - output, - "Protocol: %s\n" - "Bit: %d\n" - "Key: %08lX%08lX\n", - instance->common.name, - instance->common.code_last_count_bit, - (uint32_t)(instance->common.code_last_found >> 32), - (uint32_t)(instance->common.code_last_found & 0x00000000ffffffff)); +bool subghz_protocol_hormann_to_save_file( + SubGhzProtocolHormann* instance, + FlipperFile* flipper_file) { + return subghz_protocol_common_to_save_file((SubGhzProtocolCommon*)instance, flipper_file); } bool subghz_protocol_hormann_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolHormann* instance, const char* file_path) { - bool loaded = false; - string_t temp_str; - string_init(temp_str); - int res = 0; - int data = 0; - - do { - // Read and parse bit data from 2nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data); - if(res != 1) { - break; - } - instance->common.code_last_count_bit = (uint8_t)data; - - // Read and parse key data from 3nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - // strlen("Key: ") = 5 - string_right(temp_str, 5); - - uint8_t buf_key[8] = {0}; - if(!subghz_protocol_common_read_hex(temp_str, buf_key, 8)) { - break; - } - - for(uint8_t i = 0; i < 8; i++) { - instance->common.code_last_found = instance->common.code_last_found << 8 | buf_key[i]; - } - - loaded = true; - } while(0); - - string_clear(temp_str); - - return loaded; + return subghz_protocol_common_to_load_protocol_from_file( + (SubGhzProtocolCommon*)instance, flipper_file); } void subghz_decoder_hormann_to_load_protocol(SubGhzProtocolHormann* instance, void* context) { diff --git a/lib/subghz/protocols/subghz_protocol_hormann.h b/lib/subghz/protocols/subghz_protocol_hormann.h index 2d2276fb..6032f7a6 100644 --- a/lib/subghz/protocols/subghz_protocol_hormann.h +++ b/lib/subghz/protocols/subghz_protocol_hormann.h @@ -45,22 +45,25 @@ void subghz_protocol_hormann_parse(SubGhzProtocolHormann* instance, bool level, */ void subghz_protocol_hormann_to_str(SubGhzProtocolHormann* instance, string_t output); -/** Get a string to save the protocol +/** Adding data to a file * * @param instance - SubGhzProtocolHormann instance - * @param output - the resulting string + * @param flipper_file - FlipperFile + * @return bool */ -void subghz_protocol_hormann_to_save_str(SubGhzProtocolHormann* instance, string_t output); +bool subghz_protocol_hormann_to_save_file( + SubGhzProtocolHormann* instance, + FlipperFile* flipper_file); /** Loading protocol from file * - * @param file_worker - FileWorker file_worker + * @param flipper_file - FlipperFile * @param instance - SubGhzProtocolHormann instance * @param file_path - file path * @return bool */ bool subghz_protocol_hormann_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolHormann* instance, const char* file_path); diff --git a/lib/subghz/protocols/subghz_protocol_ido.c b/lib/subghz/protocols/subghz_protocol_ido.c index e283fa30..ce47c201 100644 --- a/lib/subghz/protocols/subghz_protocol_ido.c +++ b/lib/subghz/protocols/subghz_protocol_ido.c @@ -94,8 +94,6 @@ void subghz_protocol_ido_parse(SubGhzProtocolIDo* instance, bool level, uint32_t if((level) && (DURATION_DIFF(duration, instance->common.te_short * 10) < instance->common.te_delta * 5)) { instance->common.parser_step = IDoDecoderStepFoundPreambula; - } else { - instance->common.parser_step = IDoDecoderStepReset; } break; case IDoDecoderStepFoundPreambula: diff --git a/lib/subghz/protocols/subghz_protocol_keeloq.c b/lib/subghz/protocols/subghz_protocol_keeloq.c index 2fce7989..f3f33085 100644 --- a/lib/subghz/protocols/subghz_protocol_keeloq.c +++ b/lib/subghz/protocols/subghz_protocol_keeloq.c @@ -32,8 +32,8 @@ SubGhzProtocolKeeloq* subghz_protocol_keeloq_alloc(SubGhzKeystore* keystore) { instance->common.te_delta = 140; instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_keeloq_to_str; - instance->common.to_save_string = - (SubGhzProtocolCommonGetStrSave)subghz_protocol_keeloq_to_save_str; + instance->common.to_save_file = + (SubGhzProtocolCommonSaveFile)subghz_protocol_keeloq_to_save_file; instance->common.to_load_protocol_from_file = (SubGhzProtocolCommonLoadFromFile)subghz_protocol_keeloq_to_load_protocol_from_file; instance->common.to_load_protocol = @@ -314,10 +314,7 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, ui DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) { instance->common.parser_step = KeeloqDecoderStepCheckPreambula; instance->common.header_count++; - } else { - instance->common.parser_step = KeeloqDecoderStepReset; } - break; case KeeloqDecoderStepCheckPreambula: if((!level) && @@ -422,59 +419,16 @@ void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t outp instance->common.serial); } -void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t output) { - string_printf( - output, - "Protocol: %s\n" - "Bit: %d\n" - "Key: %08lX%08lX\n", - instance->common.name, - instance->common.code_last_count_bit, - (uint32_t)(instance->common.code_last_found >> 32), - (uint32_t)(instance->common.code_last_found & 0xFFFFFFFF)); +bool subghz_protocol_keeloq_to_save_file(SubGhzProtocolKeeloq* instance, FlipperFile* flipper_file) { + return subghz_protocol_common_to_save_file((SubGhzProtocolCommon*)instance, flipper_file); } bool subghz_protocol_keeloq_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolKeeloq* instance, const char* file_path) { - bool loaded = false; - string_t temp_str; - string_init(temp_str); - int res = 0; - int data = 0; - - do { - // Read and parse bit data from 2nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data); - if(res != 1) { - break; - } - instance->common.code_last_count_bit = (uint8_t)data; - - // Read and parse key data from 3nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - // strlen("Key: ") = 5 - string_right(temp_str, 5); - - uint8_t buf_key[8] = {0}; - if(!subghz_protocol_common_read_hex(temp_str, buf_key, 8)) { - break; - } - - for(uint8_t i = 0; i < 8; i++) { - instance->common.code_last_found = instance->common.code_last_found << 8 | buf_key[i]; - } - loaded = true; - } while(0); - string_clear(temp_str); - - return loaded; + return subghz_protocol_common_to_load_protocol_from_file( + (SubGhzProtocolCommon*)instance, flipper_file); } void subghz_decoder_keeloq_to_load_protocol(SubGhzProtocolKeeloq* instance, void* context) { diff --git a/lib/subghz/protocols/subghz_protocol_keeloq.h b/lib/subghz/protocols/subghz_protocol_keeloq.h index 4312f653..35c0c426 100644 --- a/lib/subghz/protocols/subghz_protocol_keeloq.h +++ b/lib/subghz/protocols/subghz_protocol_keeloq.h @@ -76,22 +76,23 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, ui */ void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t output); -/** Get a string to save the protocol +/** Adding data to a file * * @param instance - SubGhzProtocolKeeloq instance - * @param output - the resulting string + * @param flipper_file - FlipperFile + * @return bool */ -void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t output); +bool subghz_protocol_keeloq_to_save_file(SubGhzProtocolKeeloq* instance, FlipperFile* flipper_file); /** Loading protocol from file * - * @param file_worker - FileWorker file_worker + * @param flipper_file - FlipperFile * @param instance - SubGhzProtocolKeeloq instance * @param file_path - file path * @return bool */ bool subghz_protocol_keeloq_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolKeeloq* instance, const char* file_path); diff --git a/lib/subghz/protocols/subghz_protocol_kia.c b/lib/subghz/protocols/subghz_protocol_kia.c index 2ead7548..2046497b 100644 --- a/lib/subghz/protocols/subghz_protocol_kia.c +++ b/lib/subghz/protocols/subghz_protocol_kia.c @@ -78,8 +78,6 @@ void subghz_protocol_kia_parse(SubGhzProtocolKIA* instance, bool level, uint32_t instance->common.parser_step = KIADecoderStepCheckPreambula; instance->common.te_last = duration; instance->common.header_count = 0; - } else { - instance->common.parser_step = KIADecoderStepReset; } break; case KIADecoderStepCheckPreambula: diff --git a/lib/subghz/protocols/subghz_protocol_nero_radio.c b/lib/subghz/protocols/subghz_protocol_nero_radio.c index af2a8f1b..321a74e2 100644 --- a/lib/subghz/protocols/subghz_protocol_nero_radio.c +++ b/lib/subghz/protocols/subghz_protocol_nero_radio.c @@ -21,8 +21,8 @@ SubGhzProtocolNeroRadio* subghz_protocol_nero_radio_alloc(void) { instance->common.te_delta = 80; instance->common.type_protocol = SubGhzProtocolCommonTypeStatic; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nero_radio_to_str; - instance->common.to_save_string = - (SubGhzProtocolCommonGetStrSave)subghz_protocol_nero_radio_to_save_str; + instance->common.to_save_file = + (SubGhzProtocolCommonSaveFile)subghz_protocol_nero_radio_to_save_file; instance->common.to_load_protocol_from_file = (SubGhzProtocolCommonLoadFromFile)subghz_protocol_nero_radio_to_load_protocol_from_file; instance->common.to_load_protocol = @@ -84,23 +84,6 @@ void subghz_protocol_nero_radio_reset(SubGhzProtocolNeroRadio* instance) { instance->common.parser_step = NeroRadioDecoderStepReset; } -/** Analysis of received data - * - * @param instance SubGhzProtocolNeroRadio instance - */ -// void subghz_protocol_nero_radio_check_remote_controller(SubGhzProtocolNeroRadio* instance) { -// //пока не понятно с серийником, но код статический -// // uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_found, instance->common.code_count_bit); -// // uint32_t code_fix = code_found_reverse & 0xFFFFFFFF; -// // //uint32_t code_hop = (code_found_reverse >> 24) & 0xFFFFF; - -// // instance->common.serial = code_fix & 0xFFFFFFF; -// // instance->common.btn = (code_fix >> 28) & 0x0F; - -// //if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context); - -// } - void subghz_protocol_nero_radio_parse( SubGhzProtocolNeroRadio* instance, bool level, @@ -112,8 +95,6 @@ void subghz_protocol_nero_radio_parse( instance->common.parser_step = NeroRadioDecoderStepCheckPreambula; instance->common.te_last = duration; instance->common.header_count = 0; - } else { - instance->common.parser_step = NeroRadioDecoderStepReset; } break; case NeroRadioDecoderStepCheckPreambula: @@ -228,64 +209,18 @@ void subghz_protocol_nero_radio_to_str(SubGhzProtocolNeroRadio* instance, string code_found_reverse_lo); } -void subghz_protocol_nero_radio_to_save_str(SubGhzProtocolNeroRadio* instance, string_t output) { - uint32_t code_found_hi = instance->common.code_last_found >> 32; - uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff; - - string_printf( - output, - "Protocol: %s\n" - "Bit: %d\n" - "Key: %08lX%08lX\n", - instance->common.name, - instance->common.code_last_count_bit, - code_found_hi, - code_found_lo); +bool subghz_protocol_nero_radio_to_save_file( + SubGhzProtocolNeroRadio* instance, + FlipperFile* flipper_file) { + return subghz_protocol_common_to_save_file((SubGhzProtocolCommon*)instance, flipper_file); } bool subghz_protocol_nero_radio_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolNeroRadio* instance, const char* file_path) { - bool loaded = false; - string_t temp_str; - string_init(temp_str); - int res = 0; - int data = 0; - - do { - // Read and parse bit data from 2nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data); - if(res != 1) { - break; - } - instance->common.code_last_count_bit = (uint8_t)data; - - // Read and parse key data from 3nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - // strlen("Key: ") = 5 - string_right(temp_str, 5); - - uint8_t buf_key[8] = {0}; - if(!subghz_protocol_common_read_hex(temp_str, buf_key, 8)) { - break; - } - - for(uint8_t i = 0; i < 8; i++) { - instance->common.code_last_found = instance->common.code_last_found << 8 | buf_key[i]; - } - - loaded = true; - } while(0); - - string_clear(temp_str); - - return loaded; + return subghz_protocol_common_to_load_protocol_from_file( + (SubGhzProtocolCommon*)instance, flipper_file); } void subghz_decoder_nero_radio_to_load_protocol(SubGhzProtocolNeroRadio* instance, void* context) { diff --git a/lib/subghz/protocols/subghz_protocol_nero_radio.h b/lib/subghz/protocols/subghz_protocol_nero_radio.h index 8d00aad2..01d85836 100644 --- a/lib/subghz/protocols/subghz_protocol_nero_radio.h +++ b/lib/subghz/protocols/subghz_protocol_nero_radio.h @@ -54,22 +54,25 @@ void subghz_protocol_nero_radio_parse( */ void subghz_protocol_nero_radio_to_str(SubGhzProtocolNeroRadio* instance, string_t output); -/** Get a string to save the protocol +/** Adding data to a file * * @param instance - SubGhzProtocolNeroRadio instance - * @param output - the resulting string + * @param flipper_file - FlipperFile + * @return bool */ -void subghz_protocol_nero_radio_to_save_str(SubGhzProtocolNeroRadio* instance, string_t output); +bool subghz_protocol_nero_radio_to_save_file( + SubGhzProtocolNeroRadio* instance, + FlipperFile* flipper_file); /** Loading protocol from file * - * @param file_worker - FileWorker file_worker + * @param flipper_file - FlipperFile * @param instance - SubGhzProtocolNeroRadio instance * @param file_path - file path * @return bool */ bool subghz_protocol_nero_radio_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolNeroRadio* instance, const char* file_path); diff --git a/lib/subghz/protocols/subghz_protocol_nero_sketch.c b/lib/subghz/protocols/subghz_protocol_nero_sketch.c index c1948ecf..204ddd18 100644 --- a/lib/subghz/protocols/subghz_protocol_nero_sketch.c +++ b/lib/subghz/protocols/subghz_protocol_nero_sketch.c @@ -21,8 +21,8 @@ SubGhzProtocolNeroSketch* subghz_protocol_nero_sketch_alloc(void) { instance->common.te_delta = 150; instance->common.type_protocol = SubGhzProtocolCommonTypeStatic; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nero_sketch_to_str; - instance->common.to_save_string = - (SubGhzProtocolCommonGetStrSave)subghz_protocol_nero_sketch_to_save_str; + instance->common.to_save_file = + (SubGhzProtocolCommonSaveFile)subghz_protocol_nero_sketch_to_save_file; instance->common.to_load_protocol_from_file = (SubGhzProtocolCommonLoadFromFile)subghz_protocol_nero_sketch_to_load_protocol_from_file; instance->common.to_load_protocol = @@ -85,23 +85,6 @@ void subghz_protocol_nero_sketch_reset(SubGhzProtocolNeroSketch* instance) { instance->common.parser_step = NeroSketchDecoderStepReset; } -/** Analysis of received data - * - * @param instance SubGhzProtocolNeroSketch instance - */ -// void subghz_protocol_nero_sketch_check_remote_controller(SubGhzProtocolNeroSketch* instance) { -// //пока не понятно с серийником, но код статический -// // uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_found, instance->common.code_count_bit); -// // uint32_t code_fix = code_found_reverse & 0xFFFFFFFF; -// // //uint32_t code_hop = (code_found_reverse >> 24) & 0xFFFFF; - -// // instance->common.serial = code_fix & 0xFFFFFFF; -// // instance->common.btn = (code_fix >> 28) & 0x0F; - -// //if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context); - -// } - void subghz_protocol_nero_sketch_parse( SubGhzProtocolNeroSketch* instance, bool level, @@ -113,8 +96,6 @@ void subghz_protocol_nero_sketch_parse( instance->common.parser_step = NeroSketchDecoderStepCheckPreambula; instance->common.te_last = duration; instance->common.header_count = 0; - } else { - instance->common.parser_step = NeroSketchDecoderStepReset; } break; case NeroSketchDecoderStepCheckPreambula: @@ -221,60 +202,18 @@ void subghz_protocol_nero_sketch_to_str(SubGhzProtocolNeroSketch* instance, stri code_found_reverse_lo); } -void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, string_t output) { - uint32_t code_found_hi = instance->common.code_last_found >> 32; - uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff; - - string_printf( - output, - "Protocol: %s\n" - "Bit: %d\n" - "Key: %08lX%08lX\n", - instance->common.name, - instance->common.code_last_count_bit, - code_found_hi, - code_found_lo); +bool subghz_protocol_nero_sketch_to_save_file( + SubGhzProtocolNeroSketch* instance, + FlipperFile* flipper_file) { + return subghz_protocol_common_to_save_file((SubGhzProtocolCommon*)instance, flipper_file); } bool subghz_protocol_nero_sketch_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolNeroSketch* instance, const char* file_path) { - bool loaded = false; - string_t temp_str; - string_init(temp_str); - int res = 0; - int data = 0; - - do { - // Read and parse bit data from 2nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data); - if(res != 1) { - break; - } - instance->common.code_last_count_bit = (uint8_t)data; - - // Read and parse key data from 3nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - uint32_t temp_key_hi = 0; - uint32_t temp_key_lo = 0; - res = sscanf(string_get_cstr(temp_str), "Key: %08lX%08lX\n", &temp_key_hi, &temp_key_lo); - if(res != 2) { - break; - } - instance->common.code_last_found = (uint64_t)temp_key_hi << 32 | temp_key_lo; - - loaded = true; - } while(0); - - string_clear(temp_str); - - return loaded; + return subghz_protocol_common_to_load_protocol_from_file( + (SubGhzProtocolCommon*)instance, flipper_file); } void subghz_decoder_nero_sketch_to_load_protocol(SubGhzProtocolNeroSketch* instance, void* context) { diff --git a/lib/subghz/protocols/subghz_protocol_nero_sketch.h b/lib/subghz/protocols/subghz_protocol_nero_sketch.h index 8c3af225..33786c42 100644 --- a/lib/subghz/protocols/subghz_protocol_nero_sketch.h +++ b/lib/subghz/protocols/subghz_protocol_nero_sketch.h @@ -54,22 +54,25 @@ void subghz_protocol_nero_sketch_parse( */ void subghz_protocol_nero_sketch_to_str(SubGhzProtocolNeroSketch* instance, string_t output); -/** Get a string to save the protocol +/** Adding data to a file * * @param instance - SubGhzProtocolNeroSketch instance - * @param output - the resulting string + * @param flipper_file - FlipperFile + * @return bool */ -void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, string_t output); +bool subghz_protocol_nero_sketch_to_save_file( + SubGhzProtocolNeroSketch* instance, + FlipperFile* flipper_file); /** Loading protocol from file * - * @param file_worker - FileWorker file_worker + * @param flipper_file - FlipperFile * @param instance - SubGhzProtocolNeroSketch instance * @param file_path - file path * @return bool */ bool subghz_protocol_nero_sketch_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolNeroSketch* instance, const char* file_path); diff --git a/lib/subghz/protocols/subghz_protocol_nice_flo.c b/lib/subghz/protocols/subghz_protocol_nice_flo.c index 6c16315e..56ac43c5 100644 --- a/lib/subghz/protocols/subghz_protocol_nice_flo.c +++ b/lib/subghz/protocols/subghz_protocol_nice_flo.c @@ -27,8 +27,8 @@ SubGhzProtocolNiceFlo* subghz_protocol_nice_flo_alloc() { instance->common.te_delta = 200; instance->common.type_protocol = SubGhzProtocolCommonTypeStatic; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nice_flo_to_str; - instance->common.to_save_string = - (SubGhzProtocolCommonGetStrSave)subghz_protocol_nice_flo_to_save_str; + instance->common.to_save_file = + (SubGhzProtocolCommonSaveFile)subghz_protocol_nice_flo_to_save_file; instance->common.to_load_protocol_from_file = (SubGhzProtocolCommonLoadFromFile)subghz_protocol_nice_flo_to_load_protocol_from_file; instance->common.to_load_protocol = @@ -86,8 +86,6 @@ void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, bool level, instance->common.te_delta * 36)) { //Found header Nice Flo instance->common.parser_step = NiceFloDecoderStepFoundStartBit; - } else { - instance->common.parser_step = NiceFloDecoderStepReset; } break; case NiceFloDecoderStepFoundStartBit: @@ -166,55 +164,18 @@ void subghz_protocol_nice_flo_to_str(SubGhzProtocolNiceFlo* instance, string_t o code_found_reverse_lo); } -void subghz_protocol_nice_flo_to_save_str(SubGhzProtocolNiceFlo* instance, string_t output) { - string_printf( - output, - "Protocol: %s\n" - "Bit: %d\n" - "Key: %08lX\n", - instance->common.name, - instance->common.code_last_count_bit, - (uint32_t)(instance->common.code_last_found & 0x00000000ffffffff)); +bool subghz_protocol_nice_flo_to_save_file( + SubGhzProtocolNiceFlo* instance, + FlipperFile* flipper_file) { + return subghz_protocol_common_to_save_file((SubGhzProtocolCommon*)instance, flipper_file); } bool subghz_protocol_nice_flo_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolNiceFlo* instance, const char* file_path) { - bool loaded = false; - string_t temp_str; - string_init(temp_str); - int res = 0; - int data = 0; - - do { - // Read and parse bit data from 2nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data); - if(res != 1) { - break; - } - instance->common.code_last_count_bit = (uint8_t)data; - - // Read and parse key data from 3nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - uint32_t temp_key = 0; - res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key); - if(res != 1) { - break; - } - instance->common.code_last_found = (uint64_t)temp_key; - - loaded = true; - } while(0); - - string_clear(temp_str); - - return loaded; + return subghz_protocol_common_to_load_protocol_from_file( + (SubGhzProtocolCommon*)instance, flipper_file); } void subghz_decoder_nice_flo_to_load_protocol(SubGhzProtocolNiceFlo* instance, void* context) { diff --git a/lib/subghz/protocols/subghz_protocol_nice_flo.h b/lib/subghz/protocols/subghz_protocol_nice_flo.h index 3695fea3..a22c416b 100644 --- a/lib/subghz/protocols/subghz_protocol_nice_flo.h +++ b/lib/subghz/protocols/subghz_protocol_nice_flo.h @@ -45,22 +45,25 @@ void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, bool level, */ void subghz_protocol_nice_flo_to_str(SubGhzProtocolNiceFlo* instance, string_t output); -/** Get a string to save the protocol +/** Adding data to a file * * @param instance - SubGhzProtocolNiceFlo instance - * @param output - the resulting string + * @param flipper_file - FlipperFile + * @return bool */ -void subghz_protocol_nice_flo_to_save_str(SubGhzProtocolNiceFlo* instance, string_t output); +bool subghz_protocol_nice_flo_to_save_file( + SubGhzProtocolNiceFlo* instance, + FlipperFile* flipper_file); /** Loading protocol from file * - * @param file_worker - FileWorker file_worker + * @param flipper_file - FlipperFile * @param instance - SubGhzProtocolNiceFlo instance * @param file_path - file path * @return bool */ bool subghz_protocol_nice_flo_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolNiceFlo* instance, const char* file_path); diff --git a/lib/subghz/protocols/subghz_protocol_nice_flor_s.c b/lib/subghz/protocols/subghz_protocol_nice_flor_s.c index 95e0216a..b1b8e4ac 100644 --- a/lib/subghz/protocols/subghz_protocol_nice_flor_s.c +++ b/lib/subghz/protocols/subghz_protocol_nice_flor_s.c @@ -9,6 +9,8 @@ * https://vrtp.ru/index.php?showtopic=27867 */ +#define TAG "SubGhzNiceFlorS" + struct SubGhzProtocolNiceFlorS { SubGhzProtocolCommon common; const char* rainbow_table_file_name; @@ -45,7 +47,7 @@ void subghz_protocol_nice_flor_s_free(SubGhzProtocolNiceFlorS* instance) { void subghz_protocol_nice_flor_s_name_file(SubGhzProtocolNiceFlorS* instance, const char* name) { instance->rainbow_table_file_name = name; - printf("Loading Nice FloR S rainbow table %s\r\n", name); + FURI_LOG_I(TAG, "Loading rainbow table from %s", name); } /** Send bit @@ -166,8 +168,6 @@ void subghz_protocol_nice_flor_s_parse( instance->common.te_delta * 38)) { //Found start header Nice Flor-S instance->common.parser_step = NiceFlorSDecoderStepCheckHeader; - } else { - instance->common.parser_step = NiceFlorSDecoderStepReset; } break; case NiceFlorSDecoderStepCheckHeader: diff --git a/lib/subghz/protocols/subghz_protocol_princeton.c b/lib/subghz/protocols/subghz_protocol_princeton.c index 81b65592..238770e7 100644 --- a/lib/subghz/protocols/subghz_protocol_princeton.c +++ b/lib/subghz/protocols/subghz_protocol_princeton.c @@ -11,6 +11,8 @@ #define SUBGHZ_PT_COUNT_KEY 5 #define SUBGHZ_PT_TIMEOUT 320 +#define TAG "SubghzPrinceton" + struct SubGhzEncoderPrinceton { uint32_t key; uint16_t te; @@ -67,7 +69,7 @@ void subghz_encoder_princeton_print_log(void* context) { float duty_cycle = ((float)instance->time_high / (instance->time_high + instance->time_low)) * 100; FURI_LOG_I( - "EncoderPrinceton", + TAG "Encoder", "Radio ON=%dus, OFF=%dus, DutyCycle=%d,%d%%", instance->time_high, instance->time_low, @@ -141,8 +143,8 @@ SubGhzDecoderPrinceton* subghz_decoder_princeton_alloc(void) { instance->common.te_delta = 250; //50; instance->common.type_protocol = SubGhzProtocolCommonTypeStatic; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_decoder_princeton_to_str; - instance->common.to_save_string = - (SubGhzProtocolCommonGetStrSave)subghz_decoder_princeton_to_save_str; + instance->common.to_save_file = + (SubGhzProtocolCommonSaveFile)subghz_decoder_princeton_to_save_file; instance->common.to_load_protocol_from_file = (SubGhzProtocolCommonLoadFromFile)subghz_decoder_princeton_to_load_protocol_from_file; instance->common.to_load_protocol = @@ -210,8 +212,6 @@ void subghz_decoder_princeton_parse( instance->common.code_found = 0; instance->common.code_count_bit = 0; instance->te = 0; - } else { - instance->common.parser_step = PrincetonDecoderStepReset; } break; case PrincetonDecoderStepSaveDuration: @@ -293,68 +293,27 @@ void subghz_decoder_princeton_to_str(SubGhzDecoderPrinceton* instance, string_t instance->te); } -void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, string_t output) { - string_printf( - output, - "Protocol: %s\n" - "Bit: %d\n" - "Te: %d\n" - "Key: %08lX\n", - instance->common.name, - instance->common.code_last_count_bit, - instance->te, - (uint32_t)(instance->common.code_last_found & 0x00000000ffffffff)); +bool subghz_decoder_princeton_to_save_file( + SubGhzDecoderPrinceton* instance, + FlipperFile* flipper_file) { + bool res = subghz_protocol_common_to_save_file((SubGhzProtocolCommon*)instance, flipper_file); + if(res) { + res = flipper_file_write_uint32(flipper_file, "TE", (uint32_t*)&instance->te, 1); + if(!res) FURI_LOG_E(SUBGHZ_PARSER_TAG, "Unable to add Te"); + } + return res; } bool subghz_decoder_princeton_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzDecoderPrinceton* instance, const char* file_path) { - bool loaded = false; - string_t temp_str; - string_init(temp_str); - int res = 0; - int data = 0; - - do { - // Read and parse bit data from 2nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data); - if(res != 1) { - break; - } - instance->common.code_last_count_bit = (uint8_t)data; - - // Read and parse te data from 3nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - res = sscanf(string_get_cstr(temp_str), "Te: %d\n", &data); - if(res != 1) { - break; - } - instance->te = (uint16_t)data; - - // Read and parse key data from 4nd line - if(!file_worker_read_until(file_worker, temp_str, '\n')) { - break; - } - uint32_t temp_key = 0; - res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key); - if(res != 1) { - break; - } - instance->common.code_last_found = (uint64_t)temp_key; - instance->common.serial = instance->common.code_last_found >> 4; - instance->common.btn = (uint8_t)instance->common.code_last_found & 0x00000F; - - loaded = true; - } while(0); - - string_clear(temp_str); - + bool loaded = subghz_protocol_common_to_load_protocol_from_file( + (SubGhzProtocolCommon*)instance, flipper_file); + if(loaded) { + loaded = flipper_file_read_uint32(flipper_file, "TE", (uint32_t*)&instance->te, 1); + if(!loaded) FURI_LOG_E(SUBGHZ_PARSER_TAG, "Missing TE"); + } return loaded; } diff --git a/lib/subghz/protocols/subghz_protocol_princeton.h b/lib/subghz/protocols/subghz_protocol_princeton.h index b8c448d2..bc9bf54e 100644 --- a/lib/subghz/protocols/subghz_protocol_princeton.h +++ b/lib/subghz/protocols/subghz_protocol_princeton.h @@ -100,22 +100,25 @@ void subghz_decoder_princeton_parse( */ void subghz_decoder_princeton_to_str(SubGhzDecoderPrinceton* instance, string_t output); -/** Get a string to save the protocol +/** Adding data to a file * * @param instance - SubGhzDecoderPrinceton instance - * @param output - the resulting string + * @param flipper_file - FlipperFile + * @return bool */ -void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, string_t output); +bool subghz_decoder_princeton_to_save_file( + SubGhzDecoderPrinceton* instance, + FlipperFile* flipper_file); /** Loading protocol from file * - * @param file_worker - FileWorker file_worker + * @param flipper_file - FlipperFile * @param instance - SubGhzDecoderPrinceton instance * @param file_path - file path * @return bool */ bool subghz_decoder_princeton_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzDecoderPrinceton* instance, const char* file_path); diff --git a/lib/subghz/protocols/subghz_protocol_raw.c b/lib/subghz/protocols/subghz_protocol_raw.c index 7c711e8a..49ce87ed 100644 --- a/lib/subghz/protocols/subghz_protocol_raw.c +++ b/lib/subghz/protocols/subghz_protocol_raw.c @@ -1,15 +1,17 @@ #include "subghz_protocol_raw.h" -#include "file-worker.h" #include "../subghz_file_encoder_worker.h" +#define TAG "SubGhzRaw" + #define SUBGHZ_DOWNLOAD_MAX_SIZE 512 struct SubGhzProtocolRAW { SubGhzProtocolCommon common; - int16_t* upload_raw; + int32_t* upload_raw; uint16_t ind_write; - FileWorker* file_worker; + Storage* storage; + FlipperFile* flipper_file; SubGhzFileEncoderWorker* file_worker_encoder; uint32_t file_is_open; string_t file_name; @@ -31,7 +33,8 @@ SubGhzProtocolRAW* subghz_protocol_raw_alloc(void) { instance->last_level = false; - instance->file_worker = file_worker_alloc(false); + instance->storage = furi_record_open("storage"); + instance->flipper_file = flipper_file_alloc(instance->storage); instance->file_is_open = RAWFileIsOpenClose; string_init(instance->file_name); @@ -55,7 +58,10 @@ SubGhzProtocolRAW* subghz_protocol_raw_alloc(void) { void subghz_protocol_raw_free(SubGhzProtocolRAW* instance) { furi_assert(instance); string_clear(instance->file_name); - file_worker_free(instance->file_worker); + + flipper_file_free(instance->flipper_file); + furi_record_close("storage"); + free(instance); } @@ -120,11 +126,11 @@ void subghz_protocol_raw_to_str(SubGhzProtocolRAW* instance, string_t output) { string_cat_printf(output, "RAW Date"); } -const char* subghz_protocol_get_last_file_name(SubGhzProtocolRAW* instance) { +const char* subghz_protocol_raw_get_last_file_name(SubGhzProtocolRAW* instance) { return string_get_cstr(instance->file_name); } -void subghz_protocol_set_last_file_name(SubGhzProtocolRAW* instance, const char* name) { +void subghz_protocol_raw_set_last_file_name(SubGhzProtocolRAW* instance, const char* name) { string_printf(instance->file_name, "%s", name); } @@ -132,22 +138,21 @@ bool subghz_protocol_raw_save_to_file_init( SubGhzProtocolRAW* instance, const char* dev_name, uint32_t frequency, - FuriHalSubGhzPreset preset) { + const char* preset) { furi_assert(instance); + //instance->flipper_file = flipper_file_alloc(instance->storage); string_t dev_file_name; string_init(dev_file_name); - string_t temp_str; - string_init(temp_str); bool init = false; do { // Create subghz folder directory if necessary - if(!file_worker_mkdir(instance->file_worker, SUBGHZ_RAW_FOLDER)) { + if(!storage_simply_mkdir(instance->storage, SUBGHZ_RAW_FOLDER)) { break; } // Create saved directory if necessary - if(!file_worker_mkdir(instance->file_worker, SUBGHZ_RAW_PATH_FOLDER)) { + if(!storage_simply_mkdir(instance->storage, SUBGHZ_RAW_PATH_FOLDER)) { break; } @@ -155,61 +160,44 @@ bool subghz_protocol_raw_save_to_file_init( // First remove subghz device file if it was saved string_printf( dev_file_name, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, dev_name, SUBGHZ_APP_EXTENSION); - if(!file_worker_remove(instance->file_worker, string_get_cstr(dev_file_name))) { + + if(!storage_simply_remove(instance->storage, string_get_cstr(dev_file_name))) { break; } + // Open file - if(!file_worker_open( - instance->file_worker, string_get_cstr(dev_file_name), FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + if(!flipper_file_open_always(instance->flipper_file, string_get_cstr(dev_file_name))) { + FURI_LOG_E(TAG, "Unable to open file for write: %s", dev_file_name); break; } - // //get the name of the next free file - // file_worker_get_next_filename( - // instance->file_worker, - // SUBGHZ_RAW_PATH_FOLDER, - // dev_name, - // SUBGHZ_APP_EXTENSION, - // temp_str); - - // string_set(instance->file_name, temp_str); - - // string_printf( - // dev_file_name, - // "%s/%s%s", - // SUBGHZ_RAW_PATH_FOLDER, - // string_get_cstr(temp_str), - // SUBGHZ_APP_EXTENSION); - // // Open file - // if(!file_worker_open( - // instance->file_worker, - // string_get_cstr(dev_file_name), - // FSAM_WRITE, - // FSOM_CREATE_ALWAYS)) { - // break; - // } - - //Get string frequency preset protocol - string_printf( - temp_str, - "Frequency: %d\n" - "Preset: %d\n" - "Protocol: RAW\n", - (int)frequency, - (int)preset); - - if(!file_worker_write( - instance->file_worker, string_get_cstr(temp_str), string_size(temp_str))) { + if(!flipper_file_write_header_cstr( + instance->flipper_file, SUBGHZ_RAW_FILE_TYPE, SUBGHZ_RAW_FILE_VERSION)) { + FURI_LOG_E(TAG, "Unable to add header"); break; } - instance->upload_raw = furi_alloc(SUBGHZ_DOWNLOAD_MAX_SIZE * sizeof(uint16_t)); + if(!flipper_file_write_uint32(instance->flipper_file, "Frequency", (uint32_t*)&frequency, 1)) { + FURI_LOG_E(TAG, "Unable to add Frequency"); + break; + } + + if(!flipper_file_write_string_cstr(instance->flipper_file, "Preset", preset)) { + FURI_LOG_E(TAG, "Unable to add Preset"); + break; + } + + if(!flipper_file_write_string_cstr(instance->flipper_file, "Protocol", instance->common.name)) { + FURI_LOG_E(TAG, "Unable to add Protocol"); + break; + } + + instance->upload_raw = furi_alloc(SUBGHZ_DOWNLOAD_MAX_SIZE * sizeof(int32_t)); instance->file_is_open = RAWFileIsOpenWrite; instance->sample_write = 0; init = true; } while(0); - string_clear(temp_str); string_clear(dev_file_name); return init; @@ -225,44 +213,23 @@ void subghz_protocol_raw_save_to_file_stop(SubGhzProtocolRAW* instance) { instance->upload_raw = NULL; } - file_worker_close(instance->file_worker); + flipper_file_close(instance->flipper_file); instance->file_is_open = RAWFileIsOpenClose; } bool subghz_protocol_raw_save_to_file_write(SubGhzProtocolRAW* instance) { furi_assert(instance); - string_t temp_str; - string_init(temp_str); bool is_write = false; if(instance->file_is_open == RAWFileIsOpenWrite) { - do { - string_printf(temp_str, "RAW_Data: "); - - if(!file_worker_write( - instance->file_worker, string_get_cstr(temp_str), string_size(temp_str))) { - break; - } - - for(size_t i = 0; i < instance->ind_write - 1; i++) { - string_printf(temp_str, "%d, ", instance->upload_raw[i]); - if(!file_worker_write( - instance->file_worker, string_get_cstr(temp_str), string_size(temp_str))) { - break; - } - } - - string_printf(temp_str, "%d\n", instance->upload_raw[instance->ind_write - 1]); - if(!file_worker_write( - instance->file_worker, string_get_cstr(temp_str), string_size(temp_str))) { - break; - } - + if(!flipper_file_write_int32( + instance->flipper_file, "RAW_Data", instance->upload_raw, instance->ind_write)) { + FURI_LOG_E(TAG, "Unable to add RAW_Data"); + } else { instance->sample_write += instance->ind_write; instance->ind_write = 0; is_write = true; - } while(0); - string_clear(temp_str); + } } return is_write; } @@ -272,9 +239,10 @@ size_t subghz_protocol_raw_get_sample_write(SubGhzProtocolRAW* instance) { } bool subghz_protocol_raw_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolRAW* instance, const char* file_path) { - subghz_protocol_set_last_file_name(instance, file_path); + furi_assert(file_path); + subghz_protocol_raw_set_last_file_name(instance, file_path); return true; } \ No newline at end of file diff --git a/lib/subghz/protocols/subghz_protocol_raw.h b/lib/subghz/protocols/subghz_protocol_raw.h index 00c84314..59202b47 100644 --- a/lib/subghz/protocols/subghz_protocol_raw.h +++ b/lib/subghz/protocols/subghz_protocol_raw.h @@ -45,20 +45,20 @@ void subghz_protocol_raw_parse(SubGhzProtocolRAW* instance, bool level, uint32_t */ void subghz_protocol_raw_to_str(SubGhzProtocolRAW* instance, string_t output); -const char* subghz_protocol_get_last_file_name(SubGhzProtocolRAW* instance); +const char* subghz_protocol_raw_get_last_file_name(SubGhzProtocolRAW* instance); -void subghz_protocol_set_last_file_name(SubGhzProtocolRAW* instance, const char* name); +void subghz_protocol_raw_set_last_file_name(SubGhzProtocolRAW* instance, const char* name); bool subghz_protocol_raw_save_to_file_init( SubGhzProtocolRAW* instance, const char* dev_name, uint32_t frequency, - FuriHalSubGhzPreset preset); + const char* preset); void subghz_protocol_raw_save_to_file_stop(SubGhzProtocolRAW* instance); bool subghz_protocol_raw_save_to_file_write(SubGhzProtocolRAW* instance); size_t subghz_protocol_raw_get_sample_write(SubGhzProtocolRAW* instance); bool subghz_protocol_raw_to_load_protocol_from_file( - FileWorker* file_worker, + FlipperFile* flipper_file, SubGhzProtocolRAW* instance, const char* file_path); \ No newline at end of file diff --git a/lib/subghz/protocols/subghz_protocol_scher_khan.c b/lib/subghz/protocols/subghz_protocol_scher_khan.c index b5124f93..5f9786a0 100644 --- a/lib/subghz/protocols/subghz_protocol_scher_khan.c +++ b/lib/subghz/protocols/subghz_protocol_scher_khan.c @@ -130,8 +130,6 @@ void subghz_protocol_scher_khan_parse( instance->common.parser_step = ScherKhanDecoderStepCheckPreambula; instance->common.te_last = duration; instance->common.header_count = 0; - } else { - instance->common.parser_step = ScherKhanDecoderStepReset; } break; case ScherKhanDecoderStepCheckPreambula: diff --git a/lib/subghz/protocols/subghz_protocol_star_line.c b/lib/subghz/protocols/subghz_protocol_star_line.c index e1752b65..089a4540 100644 --- a/lib/subghz/protocols/subghz_protocol_star_line.c +++ b/lib/subghz/protocols/subghz_protocol_star_line.c @@ -238,7 +238,6 @@ void subghz_protocol_star_line_parse( instance->common.parser_step = StarLineDecoderStepCheckDuration; } } else { - instance->common.parser_step = StarLineDecoderStepReset; instance->common.header_count = 0; } break; diff --git a/lib/subghz/subghz_file_encoder_worker.c b/lib/subghz/subghz_file_encoder_worker.c index 0e502fdf..7bde91fa 100644 --- a/lib/subghz/subghz_file_encoder_worker.c +++ b/lib/subghz/subghz_file_encoder_worker.c @@ -1,25 +1,30 @@ #include "subghz_file_encoder_worker.h" #include -#include "file-worker.h" +#include +#include + +#define TAG "SubGhzFileEncoderWorker" #define SUBGHZ_FILE_ENCODER_LOAD 512 struct SubGhzFileEncoderWorker { FuriThread* thread; StreamBufferHandle_t stream; - FileWorker* file_worker; + + Storage* storage; + FlipperFile* flipper_file; volatile bool worker_running; bool level; - int16_t duration; + int32_t duration; string_t str_data; string_t file_path; }; void subghz_file_encoder_worker_add_livel_duration( SubGhzFileEncoderWorker* instance, - int16_t duration) { + int32_t duration) { bool res = true; if(duration < 0 && !instance->level) { instance->duration += duration; @@ -34,7 +39,7 @@ void subghz_file_encoder_worker_add_livel_duration( if(res) { instance->level = !instance->level; instance->duration += duration; - xStreamBufferSend(instance->stream, &instance->duration, sizeof(int16_t), 10); + xStreamBufferSend(instance->stream, &instance->duration, sizeof(int32_t), 10); instance->duration = 0; } } @@ -53,14 +58,13 @@ bool subghz_file_encoder_worker_data_parse( str1 = strchr( str1, ' '); //if found, shift the pointer by 1 element per line "RAW_Data: -1, 2, -2..." - subghz_file_encoder_worker_add_livel_duration(instance, atoi(str1)); while( - strchr(str1, ',') != NULL && + strchr(str1, ' ') != NULL && ((size_t)str1 < (len + ind_start))) { //check that there is still an element in the line and that it has not gone beyond the line - str1 = strchr(str1, ','); - str1 += 2; //if found, shift the pointer by next element per line + str1 = strchr(str1, ' '); + str1 += 1; //if found, shift the pointer by next element per line subghz_file_encoder_worker_add_livel_duration(instance, atoi(str1)); } res = true; @@ -71,12 +75,12 @@ bool subghz_file_encoder_worker_data_parse( LevelDuration subghz_file_encoder_worker_get_level_duration(void* context) { furi_assert(context); SubGhzFileEncoderWorker* instance = context; - int16_t duration; + int32_t duration; BaseType_t xHigherPriorityTaskWoken = pdFALSE; int ret = xStreamBufferReceiveFromISR( - instance->stream, &duration, sizeof(int16_t), &xHigherPriorityTaskWoken); + instance->stream, &duration, sizeof(int32_t), &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); - if(ret == sizeof(int16_t)) { + if(ret == sizeof(int32_t)) { LevelDuration level_duration = {.level = LEVEL_DURATION_RESET}; if(duration < 0) { level_duration = level_duration_make(false, duration * -1); @@ -84,11 +88,11 @@ LevelDuration subghz_file_encoder_worker_get_level_duration(void* context) { level_duration = level_duration_make(true, duration); } else if(duration == 0) { level_duration = level_duration_reset(); - FURI_LOG_I("SubGhzFileEncoderWorker", "Stop transmission"); + FURI_LOG_I(TAG, "Stop transmission"); } return level_duration; } else { - FURI_LOG_E("SubGhzFileEncoderWorker", "Slow flash read"); + FURI_LOG_E(TAG, "Slow flash read"); return level_duration_wait(); } } @@ -100,34 +104,35 @@ LevelDuration subghz_file_encoder_worker_get_level_duration(void* context) { */ static int32_t subghz_file_encoder_worker_thread(void* context) { SubGhzFileEncoderWorker* instance = context; - FURI_LOG_I("SubGhzFileEncoderWorker", "Worker start"); + FURI_LOG_I(TAG, "Worker start"); bool res = false; + File* file = flipper_file_get_file(instance->flipper_file); do { - if(!file_worker_open( - instance->file_worker, - string_get_cstr(instance->file_path), - FSAM_READ, - FSOM_OPEN_EXISTING)) { + if(!flipper_file_open_existing( + instance->flipper_file, string_get_cstr(instance->file_path))) { + FURI_LOG_E( + TAG, + "Unable to open file for read: %s", + string_get_cstr(instance->file_path)); break; } - //todo skips 3 lines file header - if(!file_worker_read_until(instance->file_worker, instance->str_data, '\n')) { - break; - } - if(!file_worker_read_until(instance->file_worker, instance->str_data, '\n')) { - break; - } - if(!file_worker_read_until(instance->file_worker, instance->str_data, '\n')) { + if(!flipper_file_read_string(instance->flipper_file, "Protocol", instance->str_data)) { + FURI_LOG_E(TAG, "Missing Protocol"); break; } + + //skip the end of the previous line "\n" + storage_file_seek(file, 1, false); res = true; - FURI_LOG_I("SubGhzFileEncoderWorker", "Start transmission"); + FURI_LOG_I(TAG, "Start transmission"); } while(0); while(res && instance->worker_running) { size_t stream_free_byte = xStreamBufferSpacesAvailable(instance->stream); - if((stream_free_byte / sizeof(int16_t)) >= SUBGHZ_FILE_ENCODER_LOAD) { - if(file_worker_read_until(instance->file_worker, instance->str_data, '\n')) { + if((stream_free_byte / sizeof(int32_t)) >= SUBGHZ_FILE_ENCODER_LOAD) { + if(file_helper_read_line(file, instance->str_data)) { + //skip the end of the previous line "\n" + storage_file_seek(file, 1, false); if(!subghz_file_encoder_worker_data_parse( instance, string_get_cstr(instance->str_data), @@ -146,11 +151,13 @@ static int32_t subghz_file_encoder_worker_thread(void* context) { } } //waiting for the end of the transfer + FURI_LOG_I(TAG, "End read file"); while(instance->worker_running) { osDelay(50); } - file_worker_close(instance->file_worker); - FURI_LOG_I("SubGhzFileEncoderWorker", "Worker stop"); + flipper_file_close(instance->flipper_file); + + FURI_LOG_I(TAG, "Worker stop"); return 0; } @@ -158,13 +165,15 @@ SubGhzFileEncoderWorker* subghz_file_encoder_worker_alloc() { SubGhzFileEncoderWorker* instance = furi_alloc(sizeof(SubGhzFileEncoderWorker)); instance->thread = furi_thread_alloc(); - furi_thread_set_name(instance->thread, "subghz_file_encoder_worker"); + furi_thread_set_name(instance->thread, "SubghzFEWorker"); furi_thread_set_stack_size(instance->thread, 2048); furi_thread_set_context(instance->thread, instance); furi_thread_set_callback(instance->thread, subghz_file_encoder_worker_thread); - instance->stream = xStreamBufferCreate(sizeof(int16_t) * 4096, sizeof(int16_t)); + instance->stream = xStreamBufferCreate(sizeof(int32_t) * 2048, sizeof(int32_t)); + + instance->storage = furi_record_open("storage"); + instance->flipper_file = flipper_file_alloc(instance->storage); - instance->file_worker = file_worker_alloc(false); string_init(instance->str_data); string_init(instance->file_path); instance->level = false; @@ -180,7 +189,9 @@ void subghz_file_encoder_worker_free(SubGhzFileEncoderWorker* instance) { string_clear(instance->str_data); string_clear(instance->file_path); - file_worker_free(instance->file_worker); + + flipper_file_free(instance->flipper_file); + furi_record_close("storage"); free(instance); } diff --git a/lib/subghz/subghz_keystore.c b/lib/subghz/subghz_keystore.c index 3b55b700..04fb80ea 100644 --- a/lib/subghz/subghz_keystore.c +++ b/lib/subghz/subghz_keystore.c @@ -7,7 +7,7 @@ #include #include -#define SUBGHZ_KEYSTORE_TAG "SubGhzParser" +#define TAG "SubGhzKeystore" #define FILE_BUFFER_SIZE 64 @@ -71,7 +71,7 @@ static bool subghz_keystore_process_line(SubGhzKeystore* instance, char* line) { subghz_keystore_add_key(instance, name, key, type); return true; } else { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Failed to load line: %s\r\n", line); + FURI_LOG_E(TAG, "Failed to load line: %s\r\n", line); return false; } } @@ -133,13 +133,13 @@ static bool subghz_keystore_read_file(SubGhzKeystore* instance, File* file, uint (uint8_t*)encrypted_line, (uint8_t*)decrypted_line, len)) { subghz_keystore_process_line(instance, decrypted_line); } else { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Decryption failed"); + FURI_LOG_E(TAG, "Decryption failed"); result = false; break; } } else { FURI_LOG_E( - SUBGHZ_KEYSTORE_TAG, "Invalid encrypted data: %s", encrypted_line); + TAG, "Invalid encrypted data: %s", encrypted_line); } } else { subghz_keystore_process_line(instance, encrypted_line); @@ -155,7 +155,7 @@ static bool subghz_keystore_read_file(SubGhzKeystore* instance, File* file, uint encrypted_line[encrypted_line_cursor] = buffer[i]; encrypted_line_cursor++; } else { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Malformed file"); + FURI_LOG_E(TAG, "Malformed file"); result = false; break; } @@ -186,21 +186,21 @@ bool subghz_keystore_load(SubGhzKeystore* instance, const char* file_name) { FlipperFile* flipper_file = flipper_file_alloc(storage); do { if(!flipper_file_open_existing(flipper_file, file_name)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to open file for read: %s", file_name); + FURI_LOG_E(TAG, "Unable to open file for read: %s", file_name); break; } if(!flipper_file_read_header(flipper_file, filetype, &version)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Missing or incorrect header"); + FURI_LOG_E(TAG, "Missing or incorrect header"); break; } if(!flipper_file_read_uint32(flipper_file, "Encryption", (uint32_t*)&encryption, 1)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Missing encryption type"); + FURI_LOG_E(TAG, "Missing encryption type"); break; } if(strcmp(string_get_cstr(filetype), SUBGHZ_KEYSTORE_FILE_TYPE) != 0 || version != SUBGHZ_KEYSTORE_FILE_VERSION) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Type or version mismatch"); + FURI_LOG_E(TAG, "Type or version mismatch"); break; } @@ -209,13 +209,13 @@ bool subghz_keystore_load(SubGhzKeystore* instance, const char* file_name) { result = subghz_keystore_read_file(instance, file, NULL); } else if(encryption == SubGhzKeystoreEncryptionAES256) { if(!flipper_file_read_hex(flipper_file, "IV", iv, 16)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Missing IV"); + FURI_LOG_E(TAG, "Missing IV"); break; } subghz_keystore_mess_with_iv(iv); result = subghz_keystore_read_file(instance, file, iv); } else { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unknown encryption"); + FURI_LOG_E(TAG, "Unknown encryption"); break; } } while(0); @@ -240,28 +240,28 @@ bool subghz_keystore_save(SubGhzKeystore* instance, const char* file_name, uint8 FlipperFile* flipper_file = flipper_file_alloc(storage); do { if(!flipper_file_open_always(flipper_file, file_name)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to open file for write: %s", file_name); + FURI_LOG_E(TAG, "Unable to open file for write: %s", file_name); break; } if(!flipper_file_write_header_cstr( flipper_file, SUBGHZ_KEYSTORE_FILE_TYPE, SUBGHZ_KEYSTORE_FILE_VERSION)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to add header"); + FURI_LOG_E(TAG, "Unable to add header"); break; } SubGhzKeystoreEncryption encryption = SubGhzKeystoreEncryptionAES256; if(!flipper_file_write_uint32(flipper_file, "Encryption", (uint32_t*)&encryption, 1)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to add Encryption"); + FURI_LOG_E(TAG, "Unable to add Encryption"); break; } if(!flipper_file_write_hex(flipper_file, "IV", iv, 16)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to add IV"); + FURI_LOG_E(TAG, "Unable to add IV"); break; } subghz_keystore_mess_with_iv(iv); if(!furi_hal_crypto_store_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to load encryption key"); + FURI_LOG_E(TAG, "Unable to load encryption key"); break; } @@ -291,7 +291,7 @@ bool subghz_keystore_save(SubGhzKeystore* instance, const char* file_name, uint8 // Form encrypted line if(!furi_hal_crypto_encrypt( (uint8_t*)decrypted_line, (uint8_t*)encrypted_line, len)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Encryption failed"); + FURI_LOG_E(TAG, "Encryption failed"); break; } // HEX Encode encrypted line @@ -307,7 +307,7 @@ bool subghz_keystore_save(SubGhzKeystore* instance, const char* file_name, uint8 encrypted_line_count++; FURI_LOG_I( - SUBGHZ_KEYSTORE_TAG, "Encrypted: `%s` -> `%s`", decrypted_line, encrypted_line); + TAG, "Encrypted: `%s` -> `%s`", decrypted_line, encrypted_line); } furi_hal_crypto_store_unload_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT); result = encrypted_line_count == SubGhzKeyArray_size(instance->data); @@ -344,26 +344,26 @@ bool subghz_keystore_raw_encrypted_save( FlipperFile* input_flipper_file = flipper_file_alloc(storage); do { if(!flipper_file_open_existing(input_flipper_file, input_file_name)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to open file for read: %s", input_file_name); + FURI_LOG_E(TAG, "Unable to open file for read: %s", input_file_name); break; } if(!flipper_file_read_header(input_flipper_file, filetype, &version)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Missing or incorrect header"); + FURI_LOG_E(TAG, "Missing or incorrect header"); break; } if(!flipper_file_read_uint32(input_flipper_file, "Encryption", (uint32_t*)&encryption, 1)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Missing encryption type"); + FURI_LOG_E(TAG, "Missing encryption type"); break; } if(strcmp(string_get_cstr(filetype), SUBGHZ_KEYSTORE_FILE_RAW_TYPE) != 0 || version != SUBGHZ_KEYSTORE_FILE_VERSION) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Type or version mismatch"); + FURI_LOG_E(TAG, "Type or version mismatch"); break; } if(encryption != SubGhzKeystoreEncryptionNone) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Already encryption"); + FURI_LOG_E(TAG, "Already encryption"); break; } File* input_file = flipper_file_get_file(input_flipper_file); @@ -371,34 +371,34 @@ bool subghz_keystore_raw_encrypted_save( FlipperFile* output_flipper_file = flipper_file_alloc(storage); if(!flipper_file_open_always(output_flipper_file, output_file_name)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to open file for write: %s", output_file_name); + FURI_LOG_E(TAG, "Unable to open file for write: %s", output_file_name); break; } if(!flipper_file_write_header_cstr( output_flipper_file, string_get_cstr(filetype), SUBGHZ_KEYSTORE_FILE_VERSION)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to add header"); + FURI_LOG_E(TAG, "Unable to add header"); break; } SubGhzKeystoreEncryption tmp_encryption = SubGhzKeystoreEncryptionAES256; if(!flipper_file_write_uint32( output_flipper_file, "Encryption", (uint32_t*)&tmp_encryption, 1)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to add Encryption"); + FURI_LOG_E(TAG, "Unable to add Encryption"); break; } if(!flipper_file_write_hex(output_flipper_file, "IV", iv, 16)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to add IV"); + FURI_LOG_E(TAG, "Unable to add IV"); break; } if(!flipper_file_write_string_cstr(output_flipper_file, "Encrypt_data", "RAW")) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to add Encrypt_data"); + FURI_LOG_E(TAG, "Unable to add Encrypt_data"); break; } subghz_keystore_mess_with_iv(iv); if(!furi_hal_crypto_store_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to load encryption key"); + FURI_LOG_E(TAG, "Unable to load encryption key"); break; } @@ -431,7 +431,7 @@ bool subghz_keystore_raw_encrypted_save( // Form encrypted line if(!furi_hal_crypto_encrypt( (uint8_t*)buffer, (uint8_t*)encrypted_line, FILE_BUFFER_SIZE / 2)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Encryption failed"); + FURI_LOG_E(TAG, "Encryption failed"); result = false; break; } @@ -483,40 +483,40 @@ bool subghz_keystore_raw_get_data(const char* file_name, size_t offset, uint8_t* FlipperFile* flipper_file = flipper_file_alloc(storage); do { if(!flipper_file_open_existing(flipper_file, file_name)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to open file for read: %s", file_name); + FURI_LOG_E(TAG, "Unable to open file for read: %s", file_name); break; } if(!flipper_file_read_header(flipper_file, str_temp, &version)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Missing or incorrect header"); + FURI_LOG_E(TAG, "Missing or incorrect header"); break; } if(!flipper_file_read_uint32(flipper_file, "Encryption", (uint32_t*)&encryption, 1)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Missing encryption type"); + FURI_LOG_E(TAG, "Missing encryption type"); break; } if(strcmp(string_get_cstr(str_temp), SUBGHZ_KEYSTORE_FILE_RAW_TYPE) != 0 || version != SUBGHZ_KEYSTORE_FILE_VERSION) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Type or version mismatch"); + FURI_LOG_E(TAG, "Type or version mismatch"); break; } File* file = flipper_file_get_file(flipper_file); if(encryption != SubGhzKeystoreEncryptionAES256) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unknown encryption"); + FURI_LOG_E(TAG, "Unknown encryption"); break; } if(offset < 16) { if(!flipper_file_read_hex(flipper_file, "IV", iv, 16)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Missing IV"); + FURI_LOG_E(TAG, "Missing IV"); break; } subghz_keystore_mess_with_iv(iv); } if(!flipper_file_read_string(flipper_file, "Encrypt_data", str_temp)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Missing Encrypt_data"); + FURI_LOG_E(TAG, "Missing Encrypt_data"); break; } @@ -537,7 +537,7 @@ bool subghz_keystore_raw_get_data(const char* file_name, size_t offset, uint8_t* size_t size = storage_file_size(file); size -= storage_file_tell(file); if(size < (offset * 2 + len * 2)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Seek position exceeds file size"); + FURI_LOG_E(TAG, "Seek position exceeds file size"); break; } @@ -555,7 +555,7 @@ bool subghz_keystore_raw_get_data(const char* file_name, size_t offset, uint8_t* } if(!furi_hal_crypto_store_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv)) { - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to load encryption key"); + FURI_LOG_E(TAG, "Unable to load encryption key"); break; } @@ -576,7 +576,7 @@ bool subghz_keystore_raw_get_data(const char* file_name, size_t offset, uint8_t* if(!furi_hal_crypto_decrypt( (uint8_t*)buffer, (uint8_t*)decrypted_line, bufer_size / 2)) { decrypted = false; - FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Decryption failed"); + FURI_LOG_E(TAG, "Decryption failed"); break; } memcpy(data, (uint8_t*)decrypted_line + (offset - (offset / 16) * 16), len); diff --git a/lib/subghz/subghz_worker.c b/lib/subghz/subghz_worker.c index 8697b394..f1f05f43 100644 --- a/lib/subghz/subghz_worker.c +++ b/lib/subghz/subghz_worker.c @@ -3,6 +3,8 @@ #include #include +#define TAG "SubGhzWorker" + struct SubGhzWorker { FuriThread* thread; StreamBufferHandle_t stream; @@ -54,7 +56,7 @@ static int32_t subghz_worker_thread_callback(void* context) { xStreamBufferReceive(instance->stream, &level_duration, sizeof(LevelDuration), 10); if(ret == sizeof(LevelDuration)) { if(level_duration_is_reset(level_duration)) { - printf("."); + FURI_LOG_E(TAG, "Overrun buffer");; if(instance->overrun_callback) instance->overrun_callback(instance->context); } else { bool level = level_duration_get_level(level_duration); @@ -90,12 +92,12 @@ SubGhzWorker* subghz_worker_alloc() { SubGhzWorker* instance = furi_alloc(sizeof(SubGhzWorker)); instance->thread = furi_thread_alloc(); - furi_thread_set_name(instance->thread, "subghz_worker"); + furi_thread_set_name(instance->thread, "SubghzWorker"); furi_thread_set_stack_size(instance->thread, 2048); furi_thread_set_context(instance->thread, instance); furi_thread_set_callback(instance->thread, subghz_worker_thread_callback); - instance->stream = xStreamBufferCreate(sizeof(LevelDuration) * 1024, sizeof(LevelDuration)); + instance->stream = xStreamBufferCreate(sizeof(LevelDuration) * 2048, sizeof(LevelDuration)); //setting filter instance->filter_running = true; diff --git a/lib/toolbox/manchester-decoder.c b/lib/toolbox/manchester-decoder.c index cbeab44a..2affe5cf 100644 --- a/lib/toolbox/manchester-decoder.c +++ b/lib/toolbox/manchester-decoder.c @@ -20,10 +20,10 @@ bool manchester_advance( new_state = manchester_reset_state; } else { if(new_state == ManchesterStateMid0) { - *data = false; + if (data) *data = false; result = true; } else if(new_state == ManchesterStateMid1) { - *data = true; + if (data) *data = true; result = true; } } diff --git a/lib/toolbox/saved_struct.c b/lib/toolbox/saved_struct.c index 61b5bdc6..653e51c8 100644 --- a/lib/toolbox/saved_struct.c +++ b/lib/toolbox/saved_struct.c @@ -3,7 +3,7 @@ #include #include -#define SAVED_STRUCT_TAG "SAVED_STRUCT" +#define TAG "SavedStruct" typedef struct { uint8_t magic; @@ -23,7 +23,7 @@ bool saved_struct_save(const char* path, furi_assert(size); SavedStructHeader header; - FURI_LOG_I(SAVED_STRUCT_TAG, "Saving \"%s\"", path); + FURI_LOG_I(TAG, "Saving \"%s\"", path); // Store Storage* storage = furi_record_open("storage"); @@ -32,7 +32,7 @@ bool saved_struct_save(const char* path, bool saved = storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS); if(!saved) { FURI_LOG_E( - SAVED_STRUCT_TAG, + TAG, "Open failed \"%s\". Error: \'%s\'", path, storage_file_get_error_desc(file)); @@ -58,7 +58,7 @@ bool saved_struct_save(const char* path, if(bytes_count != (size + sizeof(header))) { FURI_LOG_E( - SAVED_STRUCT_TAG, + TAG, "Write failed \"%s\". Error: \'%s\'", path, storage_file_get_error_desc(file)); @@ -77,7 +77,7 @@ bool saved_struct_load(const char* path, size_t size, uint8_t magic, uint8_t version) { - FURI_LOG_I(SAVED_STRUCT_TAG, "Loading \"%s\"", path); + FURI_LOG_I(TAG, "Loading \"%s\"", path); SavedStructHeader header; @@ -88,7 +88,7 @@ bool saved_struct_load(const char* path, bool loaded = storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING); if (!loaded) { FURI_LOG_E( - SAVED_STRUCT_TAG, + TAG, "Failed to read \"%s\". Error: %s", path, storage_file_get_error_desc(file)); @@ -100,14 +100,14 @@ bool saved_struct_load(const char* path, bytes_count += storage_file_read(file, data_read, size); if(bytes_count != (sizeof(SavedStructHeader) + size)) { - FURI_LOG_E(SAVED_STRUCT_TAG, "Size mismatch of file \"%s\"", path); + FURI_LOG_E(TAG, "Size mismatch of file \"%s\"", path); result = false; } } if(result && (header.magic != magic || header.version != version)) { FURI_LOG_E( - SAVED_STRUCT_TAG, + TAG, "Magic(%d != %d) or Version(%d != %d) mismatch of file \"%s\"", header.magic, magic, @@ -126,7 +126,7 @@ bool saved_struct_load(const char* path, if(header.checksum != checksum) { FURI_LOG_E( - SAVED_STRUCT_TAG, + TAG, "Checksum(%d != %d) mismatch of file \"%s\"", header.checksum, checksum,