From 432ff41d6a33478adeb012cf84f626fa89fc0e65 Mon Sep 17 00:00:00 2001 From: hedger Date: Wed, 21 Sep 2022 18:42:59 +0400 Subject: [PATCH 1/2] [FL-2844] desktop: removing slideshow file when leaving slideshow view (#1762) * [FL-2844] desktop: removing slideshow file when leaving slideshow view; vscode: fix for BM port fetcher; fap api: more symbols for LL * desktop: actually removing slideshow file * desktop: moved slideshow removal to scene code; fbt: better blackmagic device handling * fbt: disabled pagination for gdb * vscode: restored blackmagic command line * fbt: fixed debug_other target; added debug_other_blackmagic * furi: added furi_thread_suspend API group; fixed null-pointer deref for thread name; cleaned up RTOS config * furi: changed thread state check to eTaskGetState --- .vscode/example/launch.json | 4 ++ SConstruct | 13 ++++++- .../desktop/scenes/desktop_scene_slideshow.c | 8 ++-- documentation/fbt.md | 2 +- firmware/targets/f7/Inc/FreeRTOSConfig.h | 13 +------ firmware/targets/f7/api_symbols.csv | 37 ++++++++++--------- furi/core/thread.c | 25 ++++++++++++- furi/core/thread.h | 19 ++++++++++ 8 files changed, 84 insertions(+), 37 deletions(-) diff --git a/.vscode/example/launch.json b/.vscode/example/launch.json index f9470a74..7cb2542d 100644 --- a/.vscode/example/launch.json +++ b/.vscode/example/launch.json @@ -9,6 +9,10 @@ "type": "command", "command": "shellCommand.execute", "args": { + "useSingleResult": true, + "env": { + "PATH": "${workspaceFolder};${env:PATH}" + }, "command": "./fbt get_blackmagic", "description": "Get Blackmagic device", } diff --git a/SConstruct b/SConstruct index f39bba68..5ad2ac3c 100644 --- a/SConstruct +++ b/SConstruct @@ -44,6 +44,8 @@ distenv = coreenv.Clone( "target extended-remote ${GDBREMOTE}", "-ex", "set confirm off", + "-ex", + "set pagination off", ], GDBOPTS_BLACKMAGIC=[ "-ex", @@ -234,10 +236,19 @@ distenv.PhonyTarget( distenv.PhonyTarget( "debug_other", "${GDBPYCOM}", - GDBPYOPTS='-ex "source debug/PyCortexMDebug/PyCortexMDebug.py" ', + GDBOPTS="${GDBOPTS_BASE}", GDBREMOTE="${OPENOCD_GDB_PIPE}", + GDBPYOPTS='-ex "source debug/PyCortexMDebug/PyCortexMDebug.py" ', ) +distenv.PhonyTarget( + "debug_other_blackmagic", + "${GDBPYCOM}", + GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}", + GDBREMOTE="$${BLACKMAGIC_ADDR}", +) + + # Just start OpenOCD distenv.PhonyTarget( "openocd", diff --git a/applications/services/desktop/scenes/desktop_scene_slideshow.c b/applications/services/desktop/scenes/desktop_scene_slideshow.c index cab7bf62..012aff75 100644 --- a/applications/services/desktop/scenes/desktop_scene_slideshow.c +++ b/applications/services/desktop/scenes/desktop_scene_slideshow.c @@ -22,15 +22,11 @@ void desktop_scene_slideshow_on_enter(void* context) { bool desktop_scene_slideshow_on_event(void* context, SceneManagerEvent event) { Desktop* desktop = (Desktop*)context; bool consumed = false; - Storage* storage = NULL; Power* power = NULL; if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { case DesktopSlideshowCompleted: - storage = furi_record_open(RECORD_STORAGE); - storage_common_remove(storage, SLIDESHOW_FS_PATH); - furi_record_close(RECORD_STORAGE); scene_manager_previous_scene(desktop->scene_manager); consumed = true; break; @@ -50,4 +46,8 @@ bool desktop_scene_slideshow_on_event(void* context, SceneManagerEvent event) { void desktop_scene_slideshow_on_exit(void* context) { UNUSED(context); + + Storage* storage = furi_record_open(RECORD_STORAGE); + storage_common_remove(storage, SLIDESHOW_FS_PATH); + furi_record_close(RECORD_STORAGE); } diff --git a/documentation/fbt.md b/documentation/fbt.md index 3eee6baa..090ff78f 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -49,7 +49,7 @@ To run cleanup (think of `make clean`) for specified targets, add `-c` option. - `flash` - flash attached device with OpenOCD over ST-Link - `flash_usb`, `flash_usb_full` - build, upload and install update package to device over USB. See details on `updater_package`, `updater_minpackage` - `debug` - build and flash firmware, then attach with gdb with firmware's .elf loaded -- `debug_other` - attach gdb without loading any .elf. Allows to manually add external elf files with `add-symbol-file` in gdb +- `debug_other`, `debug_other_blackmagic` - attach gdb without loading any .elf. Allows to manually add external elf files with `add-symbol-file` in gdb - `updater_debug` - attach gdb with updater's .elf loaded - `blackmagic` - debug firmware with Blackmagic probe (WiFi dev board) - `openocd` - just start OpenOCD diff --git a/firmware/targets/f7/Inc/FreeRTOSConfig.h b/firmware/targets/f7/Inc/FreeRTOSConfig.h index ab2dc14e..69ef9406 100644 --- a/firmware/targets/f7/Inc/FreeRTOSConfig.h +++ b/firmware/targets/f7/Inc/FreeRTOSConfig.h @@ -76,19 +76,8 @@ to exclude the API function. */ #define INCLUDE_xTaskGetSchedulerState 1 #define INCLUDE_xTimerPendFunctionCall 1 -/* CMSIS-RTOS V2 flags */ -#define configUSE_OS2_THREAD_SUSPEND_RESUME 1 -#define configUSE_OS2_THREAD_ENUMERATE 1 -#define configUSE_OS2_THREAD_FLAGS 1 -#define configUSE_OS2_TIMER 1 -#define configUSE_OS2_MUTEX 1 - -// NEVER TO BE USED, because of their hard realtime nature -// #define configUSE_OS2_EVENTFLAGS_FROM_ISR 1 - -/* CMSIS-RTOS */ +/* Furi-specific */ #define configTASK_NOTIFICATION_ARRAY_ENTRIES 2 -#define CMSIS_TASK_NOTIFY_INDEX 1 extern __attribute__((__noreturn__)) void furi_thread_catch(); #define configTASK_RETURN_ADDRESS (furi_thread_catch + 2) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 8dff220e..ac4df046 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,1.7,, +Version,+,1.9,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -157,29 +157,29 @@ Function,-,LL_ADC_REG_Init,ErrorStatus,"ADC_TypeDef*, LL_ADC_REG_InitTypeDef*" Function,-,LL_ADC_REG_StructInit,void,LL_ADC_REG_InitTypeDef* Function,-,LL_ADC_StructInit,void,LL_ADC_InitTypeDef* Function,-,LL_COMP_DeInit,ErrorStatus,COMP_TypeDef* -Function,-,LL_COMP_Init,ErrorStatus,"COMP_TypeDef*, LL_COMP_InitTypeDef*" +Function,+,LL_COMP_Init,ErrorStatus,"COMP_TypeDef*, LL_COMP_InitTypeDef*" Function,-,LL_COMP_StructInit,void,LL_COMP_InitTypeDef* Function,-,LL_CRC_DeInit,ErrorStatus,CRC_TypeDef* Function,-,LL_CRS_DeInit,ErrorStatus, -Function,-,LL_DMA_DeInit,ErrorStatus,"DMA_TypeDef*, uint32_t" -Function,-,LL_DMA_Init,ErrorStatus,"DMA_TypeDef*, uint32_t, LL_DMA_InitTypeDef*" +Function,+,LL_DMA_DeInit,ErrorStatus,"DMA_TypeDef*, uint32_t" +Function,+,LL_DMA_Init,ErrorStatus,"DMA_TypeDef*, uint32_t, LL_DMA_InitTypeDef*" Function,-,LL_DMA_StructInit,void,LL_DMA_InitTypeDef* Function,-,LL_EXTI_DeInit,ErrorStatus, Function,-,LL_EXTI_Init,ErrorStatus,LL_EXTI_InitTypeDef* Function,-,LL_EXTI_StructInit,void,LL_EXTI_InitTypeDef* Function,-,LL_GPIO_DeInit,ErrorStatus,GPIO_TypeDef* -Function,-,LL_GPIO_Init,ErrorStatus,"GPIO_TypeDef*, LL_GPIO_InitTypeDef*" +Function,+,LL_GPIO_Init,ErrorStatus,"GPIO_TypeDef*, LL_GPIO_InitTypeDef*" Function,-,LL_GPIO_StructInit,void,LL_GPIO_InitTypeDef* Function,-,LL_I2C_DeInit,ErrorStatus,I2C_TypeDef* -Function,-,LL_I2C_Init,ErrorStatus,"I2C_TypeDef*, LL_I2C_InitTypeDef*" +Function,+,LL_I2C_Init,ErrorStatus,"I2C_TypeDef*, LL_I2C_InitTypeDef*" Function,-,LL_I2C_StructInit,void,LL_I2C_InitTypeDef* Function,-,LL_Init1msTick,void,uint32_t -Function,-,LL_LPTIM_DeInit,ErrorStatus,LPTIM_TypeDef* +Function,+,LL_LPTIM_DeInit,ErrorStatus,LPTIM_TypeDef* Function,-,LL_LPTIM_Disable,void,LPTIM_TypeDef* -Function,-,LL_LPTIM_Init,ErrorStatus,"LPTIM_TypeDef*, LL_LPTIM_InitTypeDef*" +Function,+,LL_LPTIM_Init,ErrorStatus,"LPTIM_TypeDef*, LL_LPTIM_InitTypeDef*" Function,-,LL_LPTIM_StructInit,void,LL_LPTIM_InitTypeDef* Function,-,LL_LPUART_DeInit,ErrorStatus,USART_TypeDef* -Function,-,LL_LPUART_Init,ErrorStatus,"USART_TypeDef*, LL_LPUART_InitTypeDef*" +Function,+,LL_LPUART_Init,ErrorStatus,"USART_TypeDef*, LL_LPUART_InitTypeDef*" Function,-,LL_LPUART_StructInit,void,LL_LPUART_InitTypeDef* Function,-,LL_PKA_DeInit,ErrorStatus,PKA_TypeDef* Function,-,LL_PKA_Init,ErrorStatus,"PKA_TypeDef*, LL_PKA_InitTypeDef*" @@ -193,14 +193,14 @@ Function,-,LL_RCC_GetADCClockFreq,uint32_t,uint32_t Function,-,LL_RCC_GetCLK48ClockFreq,uint32_t,uint32_t Function,-,LL_RCC_GetI2CClockFreq,uint32_t,uint32_t Function,-,LL_RCC_GetLPTIMClockFreq,uint32_t,uint32_t -Function,-,LL_RCC_GetLPUARTClockFreq,uint32_t,uint32_t +Function,+,LL_RCC_GetLPUARTClockFreq,uint32_t,uint32_t Function,-,LL_RCC_GetRFWKPClockFreq,uint32_t, Function,-,LL_RCC_GetRNGClockFreq,uint32_t,uint32_t Function,-,LL_RCC_GetRTCClockFreq,uint32_t, Function,-,LL_RCC_GetSAIClockFreq,uint32_t,uint32_t Function,-,LL_RCC_GetSMPSClockFreq,uint32_t, Function,-,LL_RCC_GetSystemClocksFreq,void,LL_RCC_ClocksTypeDef* -Function,-,LL_RCC_GetUSARTClockFreq,uint32_t,uint32_t +Function,+,LL_RCC_GetUSARTClockFreq,uint32_t,uint32_t Function,-,LL_RCC_GetUSBClockFreq,uint32_t,uint32_t Function,-,LL_RNG_DeInit,ErrorStatus,RNG_TypeDef* Function,-,LL_RNG_Init,ErrorStatus,"RNG_TypeDef*, LL_RNG_InitTypeDef*" @@ -212,21 +212,21 @@ Function,-,LL_RTC_ALMB_StructInit,void,LL_RTC_AlarmTypeDef* Function,-,LL_RTC_DATE_Init,ErrorStatus,"RTC_TypeDef*, uint32_t, LL_RTC_DateTypeDef*" Function,-,LL_RTC_DATE_StructInit,void,LL_RTC_DateTypeDef* Function,-,LL_RTC_DeInit,ErrorStatus,RTC_TypeDef* -Function,-,LL_RTC_EnterInitMode,ErrorStatus,RTC_TypeDef* +Function,+,LL_RTC_EnterInitMode,ErrorStatus,RTC_TypeDef* Function,-,LL_RTC_ExitInitMode,ErrorStatus,RTC_TypeDef* -Function,-,LL_RTC_Init,ErrorStatus,"RTC_TypeDef*, LL_RTC_InitTypeDef*" +Function,+,LL_RTC_Init,ErrorStatus,"RTC_TypeDef*, LL_RTC_InitTypeDef*" Function,-,LL_RTC_StructInit,void,LL_RTC_InitTypeDef* Function,-,LL_RTC_TIME_Init,ErrorStatus,"RTC_TypeDef*, uint32_t, LL_RTC_TimeTypeDef*" Function,-,LL_RTC_TIME_StructInit,void,LL_RTC_TimeTypeDef* Function,-,LL_RTC_WaitForSynchro,ErrorStatus,RTC_TypeDef* Function,-,LL_SPI_DeInit,ErrorStatus,SPI_TypeDef* -Function,-,LL_SPI_Init,ErrorStatus,"SPI_TypeDef*, LL_SPI_InitTypeDef*" +Function,+,LL_SPI_Init,ErrorStatus,"SPI_TypeDef*, LL_SPI_InitTypeDef*" Function,-,LL_SPI_StructInit,void,LL_SPI_InitTypeDef* Function,-,LL_SetFlashLatency,ErrorStatus,uint32_t -Function,-,LL_SetSystemCoreClock,void,uint32_t +Function,+,LL_SetSystemCoreClock,void,uint32_t Function,-,LL_TIM_BDTR_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_BDTR_InitTypeDef*" Function,-,LL_TIM_BDTR_StructInit,void,LL_TIM_BDTR_InitTypeDef* -Function,-,LL_TIM_DeInit,ErrorStatus,TIM_TypeDef* +Function,+,LL_TIM_DeInit,ErrorStatus,TIM_TypeDef* Function,-,LL_TIM_ENCODER_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_ENCODER_InitTypeDef*" Function,-,LL_TIM_ENCODER_StructInit,void,LL_TIM_ENCODER_InitTypeDef* Function,-,LL_TIM_HALLSENSOR_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_HALLSENSOR_InitTypeDef*" @@ -240,7 +240,7 @@ Function,-,LL_TIM_StructInit,void,LL_TIM_InitTypeDef* Function,-,LL_USART_ClockInit,ErrorStatus,"USART_TypeDef*, LL_USART_ClockInitTypeDef*" Function,-,LL_USART_ClockStructInit,void,LL_USART_ClockInitTypeDef* Function,-,LL_USART_DeInit,ErrorStatus,USART_TypeDef* -Function,-,LL_USART_Init,ErrorStatus,"USART_TypeDef*, LL_USART_InitTypeDef*" +Function,+,LL_USART_Init,ErrorStatus,"USART_TypeDef*, LL_USART_InitTypeDef*" Function,-,LL_USART_StructInit,void,LL_USART_InitTypeDef* Function,-,LL_mDelay,void,uint32_t Function,-,SystemCoreClockUpdate,void, @@ -1353,8 +1353,10 @@ Function,+,furi_thread_get_name,const char*,FuriThreadId Function,+,furi_thread_get_return_code,int32_t,FuriThread* Function,+,furi_thread_get_stack_space,uint32_t,FuriThreadId Function,+,furi_thread_get_state,FuriThreadState,FuriThread* +Function,+,furi_thread_is_suspended,_Bool,FuriThreadId Function,+,furi_thread_join,_Bool,FuriThread* Function,+,furi_thread_mark_as_service,void,FuriThread* +Function,+,furi_thread_resume,void,FuriThreadId Function,+,furi_thread_set_callback,void,"FuriThread*, FuriThreadCallback" Function,+,furi_thread_set_context,void,"FuriThread*, void*" Function,+,furi_thread_set_name,void,"FuriThread*, const char*" @@ -1366,6 +1368,7 @@ Function,+,furi_thread_set_stdout_callback,_Bool,FuriThreadStdoutWriteCallback Function,+,furi_thread_start,void,FuriThread* Function,+,furi_thread_stdout_flush,int32_t, Function,+,furi_thread_stdout_write,size_t,"const char*, size_t" +Function,+,furi_thread_suspend,void,FuriThreadId Function,+,furi_thread_yield,void, Function,+,furi_timer_alloc,FuriTimer*,"FuriTimerCallback, FuriTimerType, void*" Function,+,furi_timer_free,void,FuriTimer* diff --git a/furi/core/thread.c b/furi/core/thread.c index a68472b5..58cb9bc0 100644 --- a/furi/core/thread.c +++ b/furi/core/thread.c @@ -89,7 +89,9 @@ static void furi_thread_body(void* context) { if(thread->is_service) { FURI_LOG_E( - "Service", "%s thread exited. Thread memory cannot be reclaimed.", thread->name); + "Service", + "%s thread exited. Thread memory cannot be reclaimed.", + thread->name ? thread->name : ""); } // clear thread local storage @@ -515,4 +517,23 @@ size_t furi_thread_stdout_write(const char* data, size_t size) { int32_t furi_thread_stdout_flush() { return __furi_thread_stdout_flush(furi_thread_get_current()); -} \ No newline at end of file +} + +void furi_thread_suspend(FuriThreadId thread_id) { + TaskHandle_t hTask = (TaskHandle_t)thread_id; + vTaskSuspend(hTask); +} + +void furi_thread_resume(FuriThreadId thread_id) { + TaskHandle_t hTask = (TaskHandle_t)thread_id; + if(FURI_IS_IRQ_MODE()) { + xTaskResumeFromISR(hTask); + } else { + vTaskResume(hTask); + } +} + +bool furi_thread_is_suspended(FuriThreadId thread_id) { + TaskHandle_t hTask = (TaskHandle_t)thread_id; + return eTaskGetState(hTask) == eSuspended; +} diff --git a/furi/core/thread.h b/furi/core/thread.h index f15b9ff6..fda81bb3 100644 --- a/furi/core/thread.h +++ b/furi/core/thread.h @@ -236,6 +236,25 @@ size_t furi_thread_stdout_write(const char* data, size_t size); */ int32_t furi_thread_stdout_flush(); +/** Suspend thread + * + * @param thread_id thread id + */ +void furi_thread_suspend(FuriThreadId thread_id); + +/** Resume thread + * + * @param thread_id thread id + */ +void furi_thread_resume(FuriThreadId thread_id); + +/** Get thread suspended state + * + * @param thread_id thread id + * @return true if thread is suspended + */ +bool furi_thread_is_suspended(FuriThreadId thread_id); + #ifdef __cplusplus } #endif From e70121e20f00082887ec7118a58b246752976794 Mon Sep 17 00:00:00 2001 From: gornekich Date: Wed, 21 Sep 2022 18:53:25 +0300 Subject: [PATCH 2/2] [FL-2843] NFC fixes (#1764) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * nfc: fix empty desfire card message * nfc: limit total user keys to list * nfc: increase popup timeout Co-authored-by: あく --- .../scenes/nfc_scene_mf_classic_keys_list.c | 92 +++++++++++---- .../nfc/scenes/nfc_scene_mf_desfire_app.c | 111 ++++++++++-------- 2 files changed, 127 insertions(+), 76 deletions(-) diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c index 36f01897..6670ae13 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c @@ -1,48 +1,87 @@ #include "../nfc_i.h" -void nfc_scene_mf_classic_keys_list_submenu_callback(void* context, uint32_t index) { - Nfc* nfc = context; +#define NFC_SCENE_MF_CLASSIC_KEYS_LIST_MAX (100) +void nfc_scene_mf_classic_keys_list_submenu_callback(void* context, uint32_t index) { + furi_assert(context); + + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, index); } +void nfc_scene_mf_classic_keys_list_popup_callback(void* context) { + furi_assert(context); + + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); +} + +void nfc_scene_mf_classic_keys_list_prepare(Nfc* nfc, MfClassicDict* dict) { + Submenu* submenu = nfc->submenu; + uint32_t index = 0; + string_t temp_key; + string_init(temp_key); + + submenu_set_header(submenu, "Select key to delete:"); + while(mf_classic_dict_get_next_key_str(dict, temp_key)) { + char* current_key = (char*)malloc(sizeof(char) * 13); + strncpy(current_key, string_get_cstr(temp_key), 12); + MfClassicUserKeys_push_back(nfc->mfc_key_strs, current_key); + FURI_LOG_D("ListKeys", "Key %d: %s", index, current_key); + submenu_add_item( + submenu, current_key, index++, nfc_scene_mf_classic_keys_list_submenu_callback, nfc); + } + string_clear(temp_key); +} + void nfc_scene_mf_classic_keys_list_on_enter(void* context) { Nfc* nfc = context; - Submenu* submenu = nfc->submenu; MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser); - uint32_t index = 0; - string_t temp_key; MfClassicUserKeys_init(nfc->mfc_key_strs); - string_init(temp_key); if(dict) { - mf_classic_dict_rewind(dict); - while(mf_classic_dict_get_next_key_str(dict, temp_key)) { - char* current_key = (char*)malloc(sizeof(char) * 13); - strncpy(current_key, string_get_cstr(temp_key), 12); - MfClassicUserKeys_push_back(nfc->mfc_key_strs, current_key); - FURI_LOG_D("ListKeys", "Key %d: %s", index, current_key); - submenu_add_item( - submenu, - current_key, - index++, - nfc_scene_mf_classic_keys_list_submenu_callback, - nfc); + uint32_t total_user_keys = mf_classic_dict_get_total_keys(dict); + if(total_user_keys < NFC_SCENE_MF_CLASSIC_KEYS_LIST_MAX) { + nfc_scene_mf_classic_keys_list_prepare(nfc, dict); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); + } else { + popup_set_header(nfc->popup, "Too many keys!", 64, 0, AlignCenter, AlignTop); + popup_set_text( + nfc->popup, + "Edit user dictionary\nwith file browser", + 64, + 12, + AlignCenter, + AlignTop); + popup_set_callback(nfc->popup, nfc_scene_mf_classic_keys_list_popup_callback); + popup_set_context(nfc->popup, nfc); + popup_set_timeout(nfc->popup, 3000); + popup_enable_timeout(nfc->popup); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); } + mf_classic_dict_free(dict); + } else { + popup_set_header( + nfc->popup, "Failed to load dictionary", 64, 32, AlignCenter, AlignCenter); + popup_set_callback(nfc->popup, nfc_scene_mf_classic_keys_list_popup_callback); + popup_set_context(nfc->popup, nfc); + popup_set_timeout(nfc->popup, 3000); + popup_enable_timeout(nfc->popup); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); } - submenu_set_header(submenu, "Select key to delete:"); - mf_classic_dict_free(dict); - string_clear(temp_key); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } bool nfc_scene_mf_classic_keys_list_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMfClassicKeysDelete, event.event); - scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysDelete); - consumed = true; + if(event.event == NfcCustomEventViewExit) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } else { + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneMfClassicKeysDelete, event.event); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysDelete); + consumed = true; + } } return consumed; } @@ -57,4 +96,5 @@ void nfc_scene_mf_classic_keys_list_on_exit(void* context) { } MfClassicUserKeys_clear(nfc->mfc_key_strs); submenu_reset(nfc->submenu); + popup_reset(nfc->popup); } diff --git a/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c b/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c index 7faafdcf..dd842464 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c @@ -7,6 +7,13 @@ enum SubmenuIndex { SubmenuIndexDynamic, // dynamic indexes start here }; +void nfc_scene_mf_desfire_popup_callback(void* context) { + furi_assert(context); + + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); +} + MifareDesfireApplication* nfc_scene_mf_desfire_app_get_app(Nfc* nfc) { uint32_t app_idx = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp) >> 1; @@ -25,46 +32,45 @@ void nfc_scene_mf_desfire_app_submenu_callback(void* context, uint32_t index) { void nfc_scene_mf_desfire_app_on_enter(void* context) { Nfc* nfc = context; - Submenu* submenu = nfc->submenu; MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc); if(!app) { popup_set_icon(nfc->popup, 5, 5, &I_WarningDolphin_45x42); - popup_set_header(nfc->popup, "Internal Error!", 55, 12, AlignLeft, AlignBottom); - popup_set_text( - nfc->popup, - "No app selected.\nThis should\nnever happen,\nplease file a bug.", - 55, - 15, - AlignLeft, - AlignTop); + popup_set_header(nfc->popup, "Empty card!", 55, 12, AlignLeft, AlignBottom); + popup_set_callback(nfc->popup, nfc_scene_mf_desfire_popup_callback); + popup_set_context(nfc->popup, nfc); + popup_set_timeout(nfc->popup, 3000); + popup_enable_timeout(nfc->popup); + popup_set_text(nfc->popup, "No application\nfound.", 55, 15, AlignLeft, AlignTop); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - FURI_LOG_E(TAG, "Bad state. No app selected?"); - return; - } + } else { + text_box_set_font(nfc->text_box, TextBoxFontHex); + submenu_add_item( + nfc->submenu, + "App info", + SubmenuIndexAppInfo, + nfc_scene_mf_desfire_app_submenu_callback, + nfc); - text_box_set_font(nfc->text_box, TextBoxFontHex); - - submenu_add_item( - submenu, "App info", SubmenuIndexAppInfo, nfc_scene_mf_desfire_app_submenu_callback, nfc); - - uint16_t cap = NFC_TEXT_STORE_SIZE; - char* buf = nfc->text_store; - int idx = SubmenuIndexDynamic; - for(MifareDesfireFile* file = app->file_head; file; file = file->next) { - int size = snprintf(buf, cap, "File %d", file->id); - if(size < 0 || size >= cap) { - FURI_LOG_W( - TAG, - "Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated"); - break; + uint16_t cap = NFC_TEXT_STORE_SIZE; + char* buf = nfc->text_store; + int idx = SubmenuIndexDynamic; + for(MifareDesfireFile* file = app->file_head; file; file = file->next) { + int size = snprintf(buf, cap, "File %d", file->id); + if(size < 0 || size >= cap) { + FURI_LOG_W( + TAG, + "Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated"); + break; + } + char* label = buf; + cap -= size + 1; + buf += size + 1; + submenu_add_item( + nfc->submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc); } - char* label = buf; - cap -= size + 1; - buf += size + 1; - submenu_add_item(submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc); - } - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); + } } bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) { @@ -73,26 +79,30 @@ bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) { uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp); if(event.type == SceneManagerEventTypeCustom) { - MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc); - TextBox* text_box = nfc->text_box; - string_reset(nfc->text_box_store); - if(event.event == SubmenuIndexAppInfo) { - mf_df_cat_application_info(app, nfc->text_box_store); + if(event.event == NfcCustomEventViewExit) { + consumed = scene_manager_previous_scene(nfc->scene_manager); } else { - uint16_t index = event.event - SubmenuIndexDynamic; - MifareDesfireFile* file = app->file_head; - for(int i = 0; file && i < index; i++) { - file = file->next; + MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc); + TextBox* text_box = nfc->text_box; + string_reset(nfc->text_box_store); + if(event.event == SubmenuIndexAppInfo) { + mf_df_cat_application_info(app, nfc->text_box_store); + } else { + uint16_t index = event.event - SubmenuIndexDynamic; + MifareDesfireFile* file = app->file_head; + for(int i = 0; file && i < index; i++) { + file = file->next; + } + if(!file) { + return false; + } + mf_df_cat_file(file, nfc->text_box_store); } - if(!file) { - return false; - } - mf_df_cat_file(file, nfc->text_box_store); + text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state | 1); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); + consumed = true; } - text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state | 1); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); - consumed = true; } else if(event.type == SceneManagerEventTypeBack) { if(state & 1) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); @@ -108,6 +118,7 @@ void nfc_scene_mf_desfire_app_on_exit(void* context) { Nfc* nfc = context; // Clear views + popup_reset(nfc->popup); text_box_reset(nfc->text_box); string_reset(nfc->text_box_store); submenu_reset(nfc->submenu);