From 5eb045e25fbc0385f2a0296458e6b698ea06002f Mon Sep 17 00:00:00 2001 From: gornekich Date: Tue, 29 Aug 2023 08:31:40 +0400 Subject: [PATCH 01/11] nfc: add rfal wrong state error handling (#3017) --- firmware/targets/f7/furi_hal/furi_hal_nfc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index b249c8658..baffde1eb 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -701,7 +701,9 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { rfalNfcWorker(); state = rfalNfcGetState(); ret = rfalNfcDataExchangeGetStatus(); - if(ret == ERR_BUSY) { + if(ret == ERR_WRONG_STATE) { + return false; + } else if(ret == ERR_BUSY) { if(DWT->CYCCNT - start > timeout_ms * clocks_in_ms) { FURI_LOG_D(TAG, "Timeout during data exchange"); return false; From c6be6f487a1ec0d8e8b7f4af7016665d8dde0440 Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Tue, 29 Aug 2023 13:39:34 +0900 Subject: [PATCH 02/11] [FL-3495] Remove the TODO for GPIO settings save/load (#3015) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/main/gpio/scenes/gpio_scene_usb_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/main/gpio/scenes/gpio_scene_usb_uart.c b/applications/main/gpio/scenes/gpio_scene_usb_uart.c index 52b2142dc..c5e085192 100644 --- a/applications/main/gpio/scenes/gpio_scene_usb_uart.c +++ b/applications/main/gpio/scenes/gpio_scene_usb_uart.c @@ -19,7 +19,7 @@ void gpio_scene_usb_uart_on_enter(void* context) { uint32_t prev_state = scene_manager_get_scene_state(app->scene_manager, GpioAppViewUsbUart); if(prev_state == 0) { scene_usb_uart = malloc(sizeof(SceneUsbUartBridge)); - scene_usb_uart->cfg.vcp_ch = 0; // TODO FL-3495: settings load + scene_usb_uart->cfg.vcp_ch = 0; scene_usb_uart->cfg.uart_ch = 0; scene_usb_uart->cfg.flow_pins = 0; scene_usb_uart->cfg.baudrate_mode = 0; From aa1c1fd905225b02b218eb5b93aa91d6b9e9ac3e Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Tue, 29 Aug 2023 15:55:36 +0400 Subject: [PATCH 03/11] [FL-3582] SubGhz: heap overflow text error (#3021) --- applications/main/subghz/scenes/subghz_scene_receiver.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index 6ab443579..497938fee 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -123,7 +123,7 @@ void subghz_scene_receiver_on_enter(void* context) { subghz_rx_key_state_set(subghz, SubGhzRxKeyStateAddKey); } furi_string_free(str_buff); - subghz_scene_receiver_update_statusbar(subghz); + subghz_view_receiver_set_callback( subghz->subghz_receiver, subghz_scene_receiver_callback, subghz); subghz_txrx_set_rx_calback(subghz->txrx, subghz_scene_add_to_history_callback, subghz); @@ -136,6 +136,8 @@ void subghz_scene_receiver_on_enter(void* context) { furi_check( subghz_txrx_load_decoder_by_name_protocol(subghz->txrx, SUBGHZ_PROTOCOL_BIN_RAW_NAME)); + subghz_scene_receiver_update_statusbar(subghz); + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReceiver); } From 809418b9dabef8914f4f56badd12ae7a0d34f19c Mon Sep 17 00:00:00 2001 From: Sergey Gavrilov Date: Fri, 1 Sep 2023 04:23:37 +0300 Subject: [PATCH 04/11] [FL-3563] StorageListRequest: size filter (#3018) * Protobuf: size filter * Update protobuf * Scripts: types for fwflash.py * RPC: handle fliter for StorageListRequest * RPC: StorageListRequest tests for filtering * Fix unit tests configuration * Assets: sync protobuf with upstream Co-authored-by: Aleksandr Kutuzov --- applications/debug/unit_tests/rpc/rpc_test.c | 208 +++++++++++-------- applications/services/rpc/rpc_storage.c | 33 ++- assets/protobuf | 2 +- fbt_options.py | 1 + scripts/fwflash.py | 15 +- 5 files changed, 154 insertions(+), 105 deletions(-) diff --git a/applications/debug/unit_tests/rpc/rpc_test.c b/applications/debug/unit_tests/rpc/rpc_test.c index 533a8a9ca..645e75e84 100644 --- a/applications/debug/unit_tests/rpc/rpc_test.c +++ b/applications/debug/unit_tests/rpc/rpc_test.c @@ -67,7 +67,6 @@ static RpcSessionContext rpc_session[TEST_RPC_SESSIONS]; } while(0) static void output_bytes_callback(void* ctx, uint8_t* got_bytes, size_t got_size); -static void clean_directory(Storage* fs_api, const char* clean_dir); static void test_rpc_add_empty_to_list(MsgList_t msg_list, PB_CommandStatus status, uint32_t command_id); static void test_rpc_encode_and_feed(MsgList_t msg_list, uint8_t session); @@ -149,11 +148,41 @@ static void test_rpc_teardown_second_session(void) { rpc_session[1].session = NULL; } +static void test_rpc_storage_clean_directory(Storage* fs_api, const char* clean_dir) { + furi_check(fs_api); + furi_check(clean_dir); + storage_simply_remove_recursive(fs_api, clean_dir); + FS_Error error = storage_common_mkdir(fs_api, clean_dir); + furi_check(error == FSE_OK); +} + +static void test_rpc_storage_create_file(Storage* fs_api, const char* path, size_t size) { + File* file = storage_file_alloc(fs_api); + + bool success = false; + do { + if(!storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) break; + if(!storage_file_seek(file, size, true)) break; + success = true; + } while(false); + + storage_file_close(file); + storage_file_free(file); + + furi_check(success); +} + static void test_rpc_storage_setup(void) { test_rpc_setup(); Storage* fs_api = furi_record_open(RECORD_STORAGE); - clean_directory(fs_api, TEST_DIR_NAME); + test_rpc_storage_clean_directory(fs_api, TEST_DIR_NAME); + test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file100", 100); + test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file250", 250); + test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file500", 200); + test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file1000", 1000); + test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file2500", 2500); + test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file5000", 5000); furi_record_close(RECORD_STORAGE); } @@ -161,7 +190,7 @@ static void test_rpc_storage_teardown(void) { test_rpc_teardown(); Storage* fs_api = furi_record_open(RECORD_STORAGE); - clean_directory(fs_api, TEST_DIR_NAME); + test_rpc_storage_clean_directory(fs_api, TEST_DIR_NAME); furi_record_close(RECORD_STORAGE); } @@ -179,36 +208,6 @@ static void test_rpc_session_terminated_callback(void* context) { xSemaphoreGive(callbacks_context->terminate_semaphore); } -static void clean_directory(Storage* fs_api, const char* clean_dir) { - furi_check(fs_api); - furi_check(clean_dir); - - File* dir = storage_file_alloc(fs_api); - if(storage_dir_open(dir, clean_dir)) { - FileInfo fileinfo; - char* name = malloc(MAX_NAME_LENGTH + 1); - while(storage_dir_read(dir, &fileinfo, name, MAX_NAME_LENGTH)) { - size_t size = strlen(clean_dir) + strlen(name) + 1 + 1; - char* fullname = malloc(size); - snprintf(fullname, size, "%s/%s", clean_dir, name); - if(file_info_is_dir(&fileinfo)) { - clean_directory(fs_api, fullname); - } - FS_Error error = storage_common_remove(fs_api, fullname); - furi_check(error == FSE_OK); - free(fullname); - } - free(name); - } else { - FS_Error error = storage_common_mkdir(fs_api, clean_dir); - (void)error; - furi_check(error == FSE_OK); - } - - storage_dir_close(dir); - storage_file_free(dir); -} - static void test_rpc_print_message_list(MsgList_t msg_list) { #if DEBUG_PRINT MsgList_reverse(msg_list); @@ -282,24 +281,40 @@ static void test_rpc_add_ping_to_list(MsgList_t msg_list, bool request, uint32_t response->which_content = (request == PING_REQUEST) ? PB_Main_system_ping_request_tag : PB_Main_system_ping_response_tag; } +static void test_rpc_fill_basic_message(PB_Main* message, uint16_t tag, uint32_t command_id) { + message->command_id = command_id; + message->command_status = PB_CommandStatus_OK; + message->cb_content.funcs.encode = NULL; + message->which_content = tag; + message->has_next = false; +} + +static void test_rpc_create_storage_list_request( + PB_Main* message, + const char* path, + bool include_md5, + uint32_t command_id, + uint32_t filter_max_size) { + furi_check(message); + furi_check(path); + test_rpc_fill_basic_message(message, PB_Main_storage_list_request_tag, command_id); + message->content.storage_list_request.path = strdup(path); + message->content.storage_list_request.include_md5 = include_md5; + message->content.storage_list_request.filter_max_size = filter_max_size; +} static void test_rpc_create_simple_message( PB_Main* message, uint16_t tag, const char* str, - uint32_t command_id, - bool flag) { + uint32_t command_id) { furi_check(message); char* str_copy = NULL; if(str) { str_copy = strdup(str); } - message->command_id = command_id; - message->command_status = PB_CommandStatus_OK; - message->cb_content.funcs.encode = NULL; - message->which_content = tag; - message->has_next = false; + test_rpc_fill_basic_message(message, tag, command_id); switch(tag) { case PB_Main_storage_info_request_tag: message->content.storage_info_request.path = str_copy; @@ -307,10 +322,6 @@ static void test_rpc_create_simple_message( case PB_Main_storage_stat_request_tag: message->content.storage_stat_request.path = str_copy; break; - case PB_Main_storage_list_request_tag: - message->content.storage_list_request.path = str_copy; - message->content.storage_list_request.include_md5 = flag; - break; case PB_Main_storage_mkdir_request_tag: message->content.storage_mkdir_request.path = str_copy; break; @@ -573,11 +584,29 @@ static void message->content.storage_list_response.file[2].name = str; } +static bool test_rpc_system_storage_list_filter( + const FileInfo* fileinfo, + const char* name, + size_t filter_max_size) { + bool result = false; + + do { + if(!path_contains_only_ascii(name)) break; + if(filter_max_size) { + if(fileinfo->size > filter_max_size) break; + } + result = true; + } while(false); + + return result; +} + static void test_rpc_storage_list_create_expected_list( MsgList_t msg_list, const char* path, uint32_t command_id, - bool append_md5) { + bool append_md5, + size_t filter_max_size) { Storage* fs_api = furi_record_open(RECORD_STORAGE); File* dir = storage_file_alloc(fs_api); @@ -615,7 +644,7 @@ static void test_rpc_storage_list_create_expected_list( i = 0; } - if(path_contains_only_ascii(name)) { + if(test_rpc_system_storage_list_filter(&fileinfo, name, filter_max_size)) { list->file[i].type = file_info_is_dir(&fileinfo) ? PB_Storage_File_FileType_DIR : PB_Storage_File_FileType_FILE; list->file[i].size = fileinfo.size; @@ -698,17 +727,21 @@ static void test_rpc_free_msg_list(MsgList_t msg_list) { MsgList_clear(msg_list); } -static void test_rpc_storage_list_run(const char* path, uint32_t command_id, bool md5) { +static void test_rpc_storage_list_run( + const char* path, + uint32_t command_id, + bool md5, + size_t filter_max_size) { PB_Main request; MsgList_t expected_msg_list; MsgList_init(expected_msg_list); - test_rpc_create_simple_message( - &request, PB_Main_storage_list_request_tag, path, command_id, md5); + test_rpc_create_storage_list_request(&request, path, md5, command_id, filter_max_size); if(!strcmp(path, "/")) { test_rpc_storage_list_create_expected_list_root(expected_msg_list, command_id); } else { - test_rpc_storage_list_create_expected_list(expected_msg_list, path, command_id, md5); + test_rpc_storage_list_create_expected_list( + expected_msg_list, path, command_id, md5, filter_max_size); } test_rpc_encode_and_feed_one(&request, 0); test_rpc_decode_and_compare(expected_msg_list, 0); @@ -718,25 +751,32 @@ static void test_rpc_storage_list_run(const char* path, uint32_t command_id, boo } MU_TEST(test_storage_list) { - test_rpc_storage_list_run("/", ++command_id, false); - test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id, false); - test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id, false); - test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id, false); - test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id, false); - test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id, false); - test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id, false); - test_rpc_storage_list_run("error_path", ++command_id, false); + test_rpc_storage_list_run("/", ++command_id, false, 0); + test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id, false, 0); + test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id, false, 0); + test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id, false, 0); + test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id, false, 0); + test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id, false, 0); + test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id, false, 0); + test_rpc_storage_list_run("error_path", ++command_id, false, 0); } MU_TEST(test_storage_list_md5) { - test_rpc_storage_list_run("/", ++command_id, true); - test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id, true); - test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id, true); - test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id, true); - test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id, true); - test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id, true); - test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id, true); - test_rpc_storage_list_run("error_path", ++command_id, true); + test_rpc_storage_list_run("/", ++command_id, true, 0); + test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id, true, 0); + test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id, true, 0); + test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id, true, 0); + test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id, true, 0); + test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id, true, 0); + test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id, true, 0); + test_rpc_storage_list_run("error_path", ++command_id, true, 0); +} + +MU_TEST(test_storage_list_size) { + test_rpc_storage_list_run(TEST_DIR_NAME, ++command_id, false, 0); + test_rpc_storage_list_run(TEST_DIR_NAME, ++command_id, false, 1); + test_rpc_storage_list_run(TEST_DIR_NAME, ++command_id, false, 1000); + test_rpc_storage_list_run(TEST_DIR_NAME, ++command_id, false, 2500); } static void @@ -804,8 +844,7 @@ static void test_storage_read_run(const char* path, uint32_t command_id) { MsgList_init(expected_msg_list); test_rpc_add_read_to_list_by_reading_real_file(expected_msg_list, path, command_id); - test_rpc_create_simple_message( - &request, PB_Main_storage_read_request_tag, path, command_id, false); + test_rpc_create_simple_message(&request, PB_Main_storage_read_request_tag, path, command_id); test_rpc_encode_and_feed_one(&request, 0); test_rpc_decode_and_compare(expected_msg_list, 0); @@ -859,8 +898,7 @@ static void test_rpc_storage_info_run(const char* path, uint32_t command_id) { MsgList_t expected_msg_list; MsgList_init(expected_msg_list); - test_rpc_create_simple_message( - &request, PB_Main_storage_info_request_tag, path, command_id, false); + test_rpc_create_simple_message(&request, PB_Main_storage_info_request_tag, path, command_id); PB_Main* response = MsgList_push_new(expected_msg_list); response->command_id = command_id; @@ -892,8 +930,7 @@ static void test_rpc_storage_stat_run(const char* path, uint32_t command_id) { MsgList_t expected_msg_list; MsgList_init(expected_msg_list); - test_rpc_create_simple_message( - &request, PB_Main_storage_stat_request_tag, path, command_id, false); + test_rpc_create_simple_message(&request, PB_Main_storage_stat_request_tag, path, command_id); Storage* fs_api = furi_record_open(RECORD_STORAGE); FileInfo fileinfo; @@ -1005,11 +1042,7 @@ static void test_storage_write_read_run( test_rpc_add_empty_to_list(expected_msg_list, PB_CommandStatus_OK, *command_id); test_rpc_create_simple_message( - MsgList_push_raw(input_msg_list), - PB_Main_storage_read_request_tag, - path, - ++*command_id, - false); + MsgList_push_raw(input_msg_list), PB_Main_storage_read_request_tag, path, ++*command_id); test_rpc_add_read_or_write_to_list( expected_msg_list, READ_RESPONSE, @@ -1082,8 +1115,7 @@ MU_TEST(test_storage_interrupt_continuous_same_system) { MsgList_push_new(input_msg_list), PB_Main_storage_mkdir_request_tag, TEST_DIR "dir1", - command_id + 1, - false); + command_id + 1); test_rpc_add_read_or_write_to_list( input_msg_list, WRITE_REQUEST, @@ -1163,8 +1195,7 @@ static void test_storage_delete_run( MsgList_t expected_msg_list; MsgList_init(expected_msg_list); - test_rpc_create_simple_message( - &request, PB_Main_storage_delete_request_tag, path, command_id, false); + test_rpc_create_simple_message(&request, PB_Main_storage_delete_request_tag, path, command_id); request.content.storage_delete_request.recursive = recursive; test_rpc_add_empty_to_list(expected_msg_list, status, command_id); @@ -1245,8 +1276,7 @@ static void test_storage_mkdir_run(const char* path, size_t command_id, PB_Comma MsgList_t expected_msg_list; MsgList_init(expected_msg_list); - test_rpc_create_simple_message( - &request, PB_Main_storage_mkdir_request_tag, path, command_id, false); + test_rpc_create_simple_message(&request, PB_Main_storage_mkdir_request_tag, path, command_id); test_rpc_add_empty_to_list(expected_msg_list, status, command_id); test_rpc_encode_and_feed_one(&request, 0); @@ -1297,12 +1327,11 @@ static void test_storage_md5sum_run( MsgList_t expected_msg_list; MsgList_init(expected_msg_list); - test_rpc_create_simple_message( - &request, PB_Main_storage_md5sum_request_tag, path, command_id, false); + test_rpc_create_simple_message(&request, PB_Main_storage_md5sum_request_tag, path, command_id); if(status == PB_CommandStatus_OK) { PB_Main* response = MsgList_push_new(expected_msg_list); test_rpc_create_simple_message( - response, PB_Main_storage_md5sum_response_tag, md5sum, command_id, false); + response, PB_Main_storage_md5sum_response_tag, md5sum, command_id); response->command_status = status; } else { test_rpc_add_empty_to_list(expected_msg_list, status, command_id); @@ -1461,6 +1490,7 @@ MU_TEST_SUITE(test_rpc_storage) { MU_RUN_TEST(test_storage_stat); MU_RUN_TEST(test_storage_list); MU_RUN_TEST(test_storage_list_md5); + MU_RUN_TEST(test_storage_list_size); MU_RUN_TEST(test_storage_read); MU_RUN_TEST(test_storage_write_read); MU_RUN_TEST(test_storage_write); @@ -1759,8 +1789,7 @@ MU_TEST(test_rpc_multisession_storage) { MsgList_push_raw(input_0), PB_Main_storage_read_request_tag, TEST_DIR "file0.txt", - ++command_id, - false); + ++command_id); test_rpc_add_read_or_write_to_list( expected_0, READ_RESPONSE, TEST_DIR "file0.txt", pattern, sizeof(pattern), 1, command_id); @@ -1768,8 +1797,7 @@ MU_TEST(test_rpc_multisession_storage) { MsgList_push_raw(input_1), PB_Main_storage_read_request_tag, TEST_DIR "file1.txt", - ++command_id, - false); + ++command_id); test_rpc_add_read_or_write_to_list( expected_1, READ_RESPONSE, TEST_DIR "file1.txt", pattern, sizeof(pattern), 1, command_id); diff --git a/applications/services/rpc/rpc_storage.c b/applications/services/rpc/rpc_storage.c index 93c7043e8..ee024b823 100644 --- a/applications/services/rpc/rpc_storage.c +++ b/applications/services/rpc/rpc_storage.c @@ -242,6 +242,23 @@ static void rpc_system_storage_list_root(const PB_Main* request, void* context) rpc_send_and_release(session, &response); } +static bool rpc_system_storage_list_filter( + const PB_Storage_ListRequest* request, + const FileInfo* fileinfo, + const char* name) { + bool result = false; + + do { + if(!path_contains_only_ascii(name)) break; + if(request->filter_max_size) { + if(fileinfo->size > request->filter_max_size) break; + } + result = true; + } while(false); + + return result; +} + static void rpc_system_storage_list_process(const PB_Main* request, void* context) { furi_assert(request); furi_assert(context); @@ -253,9 +270,11 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex RpcSession* session = rpc_storage->session; furi_assert(session); + const PB_Storage_ListRequest* list_request = &request->content.storage_list_request; + rpc_system_storage_reset_state(rpc_storage, session, true); - if(!strcmp(request->content.storage_list_request.path, "/")) { + if(!strcmp(list_request->path, "/")) { rpc_system_storage_list_root(request, context); return; } @@ -271,7 +290,7 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex }; PB_Storage_ListResponse* list = &response.content.storage_list_response; - bool include_md5 = request->content.storage_list_request.include_md5; + bool include_md5 = list_request->include_md5; FuriString* md5 = furi_string_alloc(); FuriString* md5_path = furi_string_alloc(); File* file = storage_file_alloc(fs_api); @@ -279,7 +298,7 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex bool finish = false; int i = 0; - if(!storage_dir_open(dir, request->content.storage_list_request.path)) { + if(!storage_dir_open(dir, list_request->path)) { response.command_status = rpc_system_storage_get_file_error(dir); response.which_content = PB_Main_empty_tag; finish = true; @@ -289,7 +308,7 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex FileInfo fileinfo; char* name = malloc(MAX_NAME_LENGTH + 1); if(storage_dir_read(dir, &fileinfo, name, MAX_NAME_LENGTH)) { - if(path_contains_only_ascii(name)) { + if(rpc_system_storage_list_filter(list_request, &fileinfo, name)) { if(i == COUNT_OF(list->file)) { list->file_count = i; response.has_next = true; @@ -303,11 +322,7 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex list->file[i].name = name; if(include_md5 && !file_info_is_dir(&fileinfo)) { - furi_string_printf( //-V576 - md5_path, - "%s/%s", - request->content.storage_list_request.path, - name); + furi_string_printf(md5_path, "%s/%s", list_request->path, name); //-V576 if(md5_string_calc_file(file, furi_string_get_cstr(md5_path), md5, NULL)) { char* md5sum = list->file[i].md5sum; diff --git a/assets/protobuf b/assets/protobuf index 7e011a958..327163d58 160000 --- a/assets/protobuf +++ b/assets/protobuf @@ -1 +1 @@ -Subproject commit 7e011a95863716e72e7c6b5d552bca241d688304 +Subproject commit 327163d5867c7aa3051334c93ced718d15bfe4da diff --git a/fbt_options.py b/fbt_options.py index b6fcc70f2..bd804fc8b 100644 --- a/fbt_options.py +++ b/fbt_options.py @@ -72,6 +72,7 @@ FIRMWARE_APPS = { "unit_tests": [ "basic_services", "updater_app", + "radio_device_cc1101_ext", "unit_tests", ], } diff --git a/scripts/fwflash.py b/scripts/fwflash.py index c119aaf80..6948bd7f5 100755 --- a/scripts/fwflash.py +++ b/scripts/fwflash.py @@ -10,6 +10,7 @@ from abc import ABC, abstractmethod from dataclasses import dataclass, field from flipper.app import App +from serial.tools.list_ports_common import ListPortInfo # When adding an interface, also add it to SWD_TRANSPORT in fbt/ufbt options @@ -88,8 +89,9 @@ class OpenOCDProgrammer(Programmer): self._add_file(openocd_launch_params, self.interface.config_file) if self.serial: self._add_serial(openocd_launch_params, self.serial) - for additional_arg in self.interface.additional_args: - self._add_command(openocd_launch_params, additional_arg) + if self.interface.additional_args: + for additional_arg in self.interface.additional_args: + self._add_command(openocd_launch_params, additional_arg) self._add_file(openocd_launch_params, "target/stm32wbx.cfg") self._add_command(openocd_launch_params, "init") program_params = [ @@ -124,8 +126,9 @@ class OpenOCDProgrammer(Programmer): self._add_file(openocd_launch_params, self.interface.config_file) if self.serial: self._add_serial(openocd_launch_params, self.serial) - for additional_arg in self.interface.additional_args: - self._add_command(openocd_launch_params, additional_arg) + if self.interface.additional_args: + for additional_arg in self.interface.additional_args: + self._add_command(openocd_launch_params, additional_arg) self._add_file(openocd_launch_params, "target/stm32wbx.cfg") self._add_command(openocd_launch_params, "init") self._add_command(openocd_launch_params, "exit") @@ -167,7 +170,9 @@ def blackmagic_find_serial(serial: str): if not serial.startswith("\\\\.\\"): serial = f"\\\\.\\{serial}" - ports = list(list_ports.grep("blackmagic")) + # idk why, but python thinks that list_ports.grep returns tuple[str, str, str] + ports: list[ListPortInfo] = list(list_ports.grep("blackmagic")) # type: ignore + if len(ports) == 0: return None elif len(ports) > 2: From 7aa55ebc6c2a68afcba1392baae416d13837bab0 Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:47:02 +0900 Subject: [PATCH 05/11] [FL-3543] Check the filetype of the update manifest (#3025) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- lib/update_util/update_manifest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/update_util/update_manifest.c b/lib/update_util/update_manifest.c index 47b2cc0b9..42ab073b0 100644 --- a/lib/update_util/update_manifest.c +++ b/lib/update_util/update_manifest.c @@ -54,10 +54,10 @@ static bool FuriString* filetype; - // TODO FL-3543: compare filetype? filetype = furi_string_alloc(); update_manifest->valid = flipper_format_read_header(flipper_file, filetype, &update_manifest->manifest_version) && + furi_string_cmp_str(filetype, "Flipper firmware upgrade configuration") == 0 && flipper_format_read_string(flipper_file, MANIFEST_KEY_INFO, update_manifest->version) && flipper_format_read_uint32( flipper_file, MANIFEST_KEY_TARGET, &update_manifest->target, 1) && From f218c41d835354e382806ed6c44f1582a322279f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Fri, 1 Sep 2023 10:54:52 +0900 Subject: [PATCH 06/11] Undo some TODO (#3024) * TODO FL-3497: impossible to fix with current memory allocator * TODO FL-3497: removed, requires radically different settings approach * TODO FL-3514: removed, yes we should * TODO FL-3498: implemented, guarding view port access with mutex. * TODO FL-3515: removed, questionable but ok * TODO FL-3510: removed, comment added * TODO FL-3500: refactored, store pin numbers in GpioPinRecord, fix gpio app crash caused by incorrect gpio_pins traversal. * Format Sources * TODO FL-3505: removed, mutex alone is not going to fix issue with WPAN architecture * TODO FL-3506: removed, change ownership by copy is good * TODO FL-3519: documentation and link to source added * Lib: remove unneded total sum from comment in bq27220 --------- Co-authored-by: hedger --- .../debug/unit_tests/furi/furi_memmgr_test.c | 1 - applications/main/gpio/gpio_items.c | 8 +- applications/services/desktop/desktop.c | 3 - applications/services/gui/gui.c | 7 +- applications/services/gui/view_dispatcher.c | 1 - applications/services/gui/view_port.c | 46 +++++++-- applications/services/gui/view_port_i.h | 1 + .../services/power/power_service/power.c | 2 +- .../targets/f18/furi_hal/furi_hal_resources.c | 95 ++++++++++--------- .../targets/f18/furi_hal/furi_hal_resources.h | 1 + firmware/targets/f7/ble_glue/ble_glue.c | 1 - .../targets/f7/ble_glue/services/gatt_char.c | 1 - .../targets/f7/furi_hal/furi_hal_resources.c | 58 ++++++----- .../targets/f7/furi_hal/furi_hal_resources.h | 1 + lib/drivers/bq27220.c | 9 +- 15 files changed, 137 insertions(+), 98 deletions(-) diff --git a/applications/debug/unit_tests/furi/furi_memmgr_test.c b/applications/debug/unit_tests/furi/furi_memmgr_test.c index 05d967a99..a28632cf4 100644 --- a/applications/debug/unit_tests/furi/furi_memmgr_test.c +++ b/applications/debug/unit_tests/furi/furi_memmgr_test.c @@ -26,7 +26,6 @@ void test_furi_memmgr() { mu_assert_int_eq(66, ((uint8_t*)ptr)[i]); } - // TODO FL-3492: fix realloc to copy only old size, and write testcase that leftover of reallocated memory is zero-initialized free(ptr); // allocate and zero-initialize array (calloc) diff --git a/applications/main/gpio/gpio_items.c b/applications/main/gpio/gpio_items.c index 02f7d95b0..746abe032 100644 --- a/applications/main/gpio/gpio_items.c +++ b/applications/main/gpio/gpio_items.c @@ -18,10 +18,12 @@ GPIOItems* gpio_items_alloc() { } items->pins = malloc(sizeof(GpioPinRecord) * items->count); - for(size_t i = 0; i < items->count; i++) { + size_t index = 0; + for(size_t i = 0; i < gpio_pins_count; i++) { if(!gpio_pins[i].debug) { - items->pins[i].pin = gpio_pins[i].pin; - items->pins[i].name = gpio_pins[i].name; + items->pins[index].pin = gpio_pins[i].pin; + items->pins[index].name = gpio_pins[i].name; + index++; } } return items; diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 0627652ab..547883e9a 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -101,7 +101,6 @@ static void desktop_clock_draw_callback(Canvas* canvas, void* context) { char buffer[20]; snprintf(buffer, sizeof(buffer), "%02u:%02u", hour, desktop->time_minute); - // TODO FL-3515: never do that, may cause visual glitches view_port_set_width( desktop->clock_viewport, canvas_string_width(canvas, buffer) - 1 + (desktop->time_minute % 10 == 1)); @@ -126,8 +125,6 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { return true; case DesktopGlobalAfterAppFinished: animation_manager_load_and_continue_animation(desktop->animation_manager); - // TODO FL-3497: Implement a message mechanism for loading settings and (optionally) - // locking and unlocking DESKTOP_SETTINGS_LOAD(&desktop->settings); desktop_clock_reconfigure(desktop); diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index b96f89db9..0bdc999b7 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -361,10 +361,11 @@ void gui_add_view_port(Gui* gui, ViewPort* view_port, GuiLayer layer) { furi_assert(view_port); furi_check(layer < GuiLayerMAX); // Only fullscreen supports Vertical orientation for now - furi_assert( + ViewPortOrientation view_port_orientation = view_port_get_orientation(view_port); + furi_check( (layer == GuiLayerFullscreen) || - ((view_port->orientation != ViewPortOrientationVertical) && - (view_port->orientation != ViewPortOrientationVerticalFlip))); + ((view_port_orientation != ViewPortOrientationVertical) && + (view_port_orientation != ViewPortOrientationVerticalFlip))); gui_lock(gui); // Verify that view port is not yet added diff --git a/applications/services/gui/view_dispatcher.c b/applications/services/gui/view_dispatcher.c index 83f0edbea..0119abc20 100644 --- a/applications/services/gui/view_dispatcher.c +++ b/applications/services/gui/view_dispatcher.c @@ -272,7 +272,6 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e } else if(view_dispatcher->navigation_event_callback) { // Dispatch navigation event if(!view_dispatcher->navigation_event_callback(view_dispatcher->event_context)) { - // TODO FL-3514: should we allow view_dispatcher to stop without navigation_event_callback? view_dispatcher_stop(view_dispatcher); return; } diff --git a/applications/services/gui/view_port.c b/applications/services/gui/view_port.c index 57c0fddb4..0f300c168 100644 --- a/applications/services/gui/view_port.c +++ b/applications/services/gui/view_port.c @@ -7,8 +7,6 @@ #include "gui.h" #include "gui_i.h" -// TODO FL-3498: add mutex to view_port ops - _Static_assert(ViewPortOrientationMAX == 4, "Incorrect ViewPortOrientation count"); _Static_assert( (ViewPortOrientationHorizontal == 0 && ViewPortOrientationHorizontalFlip == 1 && @@ -95,52 +93,73 @@ ViewPort* view_port_alloc() { ViewPort* view_port = malloc(sizeof(ViewPort)); view_port->orientation = ViewPortOrientationHorizontal; view_port->is_enabled = true; + view_port->mutex = furi_mutex_alloc(FuriMutexTypeRecursive); return view_port; } void view_port_free(ViewPort* view_port) { furi_assert(view_port); + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); furi_check(view_port->gui == NULL); + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); + furi_mutex_free(view_port->mutex); free(view_port); } void view_port_set_width(ViewPort* view_port, uint8_t width) { furi_assert(view_port); + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); view_port->width = width; + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); } uint8_t view_port_get_width(const ViewPort* view_port) { furi_assert(view_port); - return view_port->width; + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); + uint8_t width = view_port->width; + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); + return width; } void view_port_set_height(ViewPort* view_port, uint8_t height) { furi_assert(view_port); + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); view_port->height = height; + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); } uint8_t view_port_get_height(const ViewPort* view_port) { furi_assert(view_port); - return view_port->height; + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); + uint8_t height = view_port->height; + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); + return height; } void view_port_enabled_set(ViewPort* view_port, bool enabled) { furi_assert(view_port); + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); if(view_port->is_enabled != enabled) { view_port->is_enabled = enabled; if(view_port->gui) gui_update(view_port->gui); } + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); } bool view_port_is_enabled(const ViewPort* view_port) { furi_assert(view_port); - return view_port->is_enabled; + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); + bool is_enabled = view_port->is_enabled; + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); + return is_enabled; } void view_port_draw_callback_set(ViewPort* view_port, ViewPortDrawCallback callback, void* context) { furi_assert(view_port); + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); view_port->draw_callback = callback; view_port->draw_callback_context = context; + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); } void view_port_input_callback_set( @@ -148,34 +167,43 @@ void view_port_input_callback_set( ViewPortInputCallback callback, void* context) { furi_assert(view_port); + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); view_port->input_callback = callback; view_port->input_callback_context = context; + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); } void view_port_update(ViewPort* view_port) { furi_assert(view_port); + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); if(view_port->gui && view_port->is_enabled) gui_update(view_port->gui); + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); } void view_port_gui_set(ViewPort* view_port, Gui* gui) { furi_assert(view_port); + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); view_port->gui = gui; + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); } void view_port_draw(ViewPort* view_port, Canvas* canvas) { furi_assert(view_port); furi_assert(canvas); + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); furi_check(view_port->gui); if(view_port->draw_callback) { view_port_setup_canvas_orientation(view_port, canvas); view_port->draw_callback(canvas, view_port->draw_callback_context); } + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); } void view_port_input(ViewPort* view_port, InputEvent* event) { furi_assert(view_port); furi_assert(event); + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); furi_check(view_port->gui); if(view_port->input_callback) { @@ -183,13 +211,19 @@ void view_port_input(ViewPort* view_port, InputEvent* event) { view_port_map_input(event, orientation); view_port->input_callback(event, view_port->input_callback_context); } + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); } void view_port_set_orientation(ViewPort* view_port, ViewPortOrientation orientation) { furi_assert(view_port); + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); view_port->orientation = orientation; + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); } ViewPortOrientation view_port_get_orientation(const ViewPort* view_port) { - return view_port->orientation; + furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk); + ViewPortOrientation orientation = view_port->orientation; + furi_check(furi_mutex_release(view_port->mutex) == FuriStatusOk); + return orientation; } diff --git a/applications/services/gui/view_port_i.h b/applications/services/gui/view_port_i.h index 90f48ac93..444e1a27c 100644 --- a/applications/services/gui/view_port_i.h +++ b/applications/services/gui/view_port_i.h @@ -10,6 +10,7 @@ struct ViewPort { Gui* gui; + FuriMutex* mutex; bool is_enabled; ViewPortOrientation orientation; diff --git a/applications/services/power/power_service/power.c b/applications/services/power/power_service/power.c index e39a84eaf..ad3a5114d 100644 --- a/applications/services/power/power_service/power.c +++ b/applications/services/power/power_service/power.c @@ -30,7 +30,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) { if(power->state == PowerStateCharging) { canvas_set_bitmap_mode(canvas, 1); canvas_set_color(canvas, ColorWhite); - // TODO FL-3510: replace -1 magic for uint8_t with re-framing + // -1 used here to overflow u8 number and render is outside of the area canvas_draw_icon(canvas, 8, -1, &I_Charging_lightning_mask_9x10); canvas_set_color(canvas, ColorBlack); canvas_draw_icon(canvas, 8, -1, &I_Charging_lightning_9x10); diff --git a/firmware/targets/f18/furi_hal/furi_hal_resources.c b/firmware/targets/f18/furi_hal/furi_hal_resources.c index 63da03e04..efd39977b 100644 --- a/firmware/targets/f18/furi_hal/furi_hal_resources.c +++ b/firmware/targets/f18/furi_hal/furi_hal_resources.c @@ -67,35 +67,53 @@ const GpioPin gpio_usb_dm = {.port = GPIOA, .pin = LL_GPIO_PIN_11}; const GpioPin gpio_usb_dp = {.port = GPIOA, .pin = LL_GPIO_PIN_12}; const GpioPinRecord gpio_pins[] = { - {.pin = &gpio_ext_pa7, .name = "PA7", .debug = false}, - {.pin = &gpio_ext_pa6, .name = "PA6", .debug = false}, - {.pin = &gpio_ext_pa4, .name = "PA4", .debug = false}, - {.pin = &gpio_ext_pb3, .name = "PB3", .debug = false}, - {.pin = &gpio_ext_pb2, .name = "PB2", .debug = false}, - {.pin = &gpio_ext_pc3, .name = "PC3", .debug = false}, - {.pin = &gpio_ext_pc1, .name = "PC1", .debug = false}, - {.pin = &gpio_ext_pc0, .name = "PC0", .debug = false}, + // 5V: 1 + {.pin = &gpio_ext_pa7, .name = "PA7", .number = 2, .debug = false}, + {.pin = &gpio_ext_pa6, .name = "PA6", .number = 3, .debug = false}, + {.pin = &gpio_ext_pa4, .name = "PA4", .number = 4, .debug = false}, + {.pin = &gpio_ext_pb3, .name = "PB3", .number = 5, .debug = false}, + {.pin = &gpio_ext_pb2, .name = "PB2", .number = 6, .debug = false}, + {.pin = &gpio_ext_pc3, .name = "PC3", .number = 7, .debug = false}, + // GND: 8 + // Space + // 3v3: 9 + {.pin = &gpio_swclk, .name = "PA14", .number = 10, .debug = true}, + // GND: 11 + {.pin = &gpio_swdio, .name = "PA13", .number = 12, .debug = true}, + {.pin = &gpio_usart_tx, .name = "PB6", .number = 13, .debug = true}, + {.pin = &gpio_usart_rx, .name = "PB7", .number = 14, .debug = true}, + {.pin = &gpio_ext_pc1, .name = "PC1", .number = 15, .debug = false}, + {.pin = &gpio_ext_pc0, .name = "PC0", .number = 16, .debug = false}, + {.pin = &gpio_ibutton, .name = "PB14", .number = 17, .debug = true}, + // GND: 18 - {.pin = &gpio_ext_pc5, .name = "PC5", .debug = false}, - {.pin = &gpio_ext_pc4, .name = "PC4", .debug = false}, - {.pin = &gpio_ext_pa5, .name = "PA5", .debug = false}, - {.pin = &gpio_ext_pb9, .name = "PB9", .debug = false}, - {.pin = &gpio_ext_pa0, .name = "PA0", .debug = false}, - {.pin = &gpio_ext_pa1, .name = "PA1", .debug = false}, - {.pin = &gpio_ext_pa15, .name = "PA15", .debug = false}, - {.pin = &gpio_ext_pe4, .name = "PE4", .debug = false}, - {.pin = &gpio_ext_pa2, .name = "PA2", .debug = false}, - {.pin = &gpio_ext_pb4, .name = "PB4", .debug = false}, - {.pin = &gpio_ext_pb5, .name = "PB5", .debug = false}, - {.pin = &gpio_ext_pd0, .name = "PD0", .debug = false}, - {.pin = &gpio_ext_pb13, .name = "PB13", .debug = false}, + // 2nd column + // 5V: 19 + {.pin = &gpio_ext_pc5, .name = "PC5", .number = 20, .debug = false}, + {.pin = &gpio_ext_pc4, .name = "PC4", .number = 21, .debug = false}, + {.pin = &gpio_ext_pa5, .name = "PA5", .number = 22, .debug = false}, + {.pin = &gpio_ext_pb9, .name = "PB9", .number = 23, .debug = false}, + {.pin = &gpio_ext_pa0, .name = "PA0", .number = 24, .debug = false}, + {.pin = &gpio_ext_pa1, .name = "PA1", .number = 25, .debug = false}, + // KEY: 26 + // Space + // 3v3: 27 + {.pin = &gpio_ext_pa15, .name = "PA15", .number = 28, .debug = false}, + // GND: 29 + {.pin = &gpio_ext_pe4, .name = "PE4", .number = 30, .debug = false}, + {.pin = &gpio_ext_pa2, .name = "PA2", .number = 31, .debug = false}, + {.pin = &gpio_ext_pb4, .name = "PB4", .number = 32, .debug = false}, + {.pin = &gpio_ext_pb5, .name = "PB5", .number = 33, .debug = false}, + {.pin = &gpio_ext_pd0, .name = "PD0", .number = 34, .debug = false}, + {.pin = &gpio_ext_pb13, .name = "PB13", .number = 35, .debug = false}, + // GND: 36 /* Dangerous pins, may damage hardware */ - {.pin = &gpio_usart_rx, .name = "PB7", .debug = true}, - {.pin = &gpio_speaker, .name = "PB8", .debug = true}, + {.pin = &gpio_usart_rx, .name = "PB7", .number = 0, .debug = true}, + {.pin = &gpio_speaker, .name = "PB8", .number = 0, .debug = true}, }; -const size_t gpio_pins_count = sizeof(gpio_pins) / sizeof(GpioPinRecord); +const size_t gpio_pins_count = COUNT_OF(gpio_pins); const InputPin input_pins[] = { {.gpio = &gpio_button_up, .key = InputKeyUp, .inverted = true, .name = "Up"}, @@ -106,7 +124,7 @@ const InputPin input_pins[] = { {.gpio = &gpio_button_back, .key = InputKeyBack, .inverted = true, .name = "Back"}, }; -const size_t input_pins_count = sizeof(input_pins) / sizeof(InputPin); +const size_t input_pins_count = COUNT_OF(input_pins); static void furi_hal_resources_init_input_pins(GpioMode mode) { for(size_t i = 0; i < input_pins_count; i++) { @@ -216,25 +234,10 @@ void furi_hal_resources_init() { } int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio) { - // TODO FL-3500: describe second ROW - if(gpio == &gpio_ext_pa7) - return 2; - else if(gpio == &gpio_ext_pa6) - return 3; - else if(gpio == &gpio_ext_pa4) - return 4; - else if(gpio == &gpio_ext_pb3) - return 5; - else if(gpio == &gpio_ext_pb2) - return 6; - else if(gpio == &gpio_ext_pc3) - return 7; - else if(gpio == &gpio_ext_pc1) - return 15; - else if(gpio == &gpio_ext_pc0) - return 16; - else if(gpio == &gpio_ibutton) - return 17; - else - return -1; + for(size_t i = 0; i < gpio_pins_count; i++) { + if(gpio_pins[i].pin == gpio) { + return gpio_pins[i].number; + } + } + return -1; } diff --git a/firmware/targets/f18/furi_hal/furi_hal_resources.h b/firmware/targets/f18/furi_hal/furi_hal_resources.h index 7d2caab36..fed7802a5 100644 --- a/firmware/targets/f18/furi_hal/furi_hal_resources.h +++ b/firmware/targets/f18/furi_hal/furi_hal_resources.h @@ -41,6 +41,7 @@ typedef struct { typedef struct { const GpioPin* pin; const char* name; + const uint8_t number; const bool debug; } GpioPinRecord; diff --git a/firmware/targets/f7/ble_glue/ble_glue.c b/firmware/targets/f7/ble_glue/ble_glue.c index 746df71c7..2c30612b5 100644 --- a/firmware/targets/f7/ble_glue/ble_glue.c +++ b/firmware/targets/f7/ble_glue/ble_glue.c @@ -222,7 +222,6 @@ bool ble_glue_wait_for_c2_start(int32_t timeout) { bool started = false; do { - // TODO FL-3505: use mutex? started = ble_glue->status == BleGlueStatusC2Started; if(!started) { timeout--; diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.c b/firmware/targets/f7/ble_glue/services/gatt_char.c index e0539c34f..f6e27f53e 100644 --- a/firmware/targets/f7/ble_glue/services/gatt_char.c +++ b/firmware/targets/f7/ble_glue/services/gatt_char.c @@ -14,7 +14,6 @@ void flipper_gatt_characteristic_init( furi_assert(char_instance); // Copy the descriptor to the instance, since it may point to stack memory - // TODO FL-3506: only copy if really comes from stack char_instance->characteristic = malloc(sizeof(FlipperGattCharacteristicParams)); memcpy( (void*)char_instance->characteristic, diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.c b/firmware/targets/f7/furi_hal/furi_hal_resources.c index 4d52960d8..d519484d1 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.c +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.c @@ -69,22 +69,32 @@ const GpioPin gpio_usb_dm = {.port = GPIOA, .pin = LL_GPIO_PIN_11}; const GpioPin gpio_usb_dp = {.port = GPIOA, .pin = LL_GPIO_PIN_12}; const GpioPinRecord gpio_pins[] = { - {.pin = &gpio_ext_pa7, .name = "PA7", .debug = false}, - {.pin = &gpio_ext_pa6, .name = "PA6", .debug = false}, - {.pin = &gpio_ext_pa4, .name = "PA4", .debug = false}, - {.pin = &gpio_ext_pb3, .name = "PB3", .debug = false}, - {.pin = &gpio_ext_pb2, .name = "PB2", .debug = false}, - {.pin = &gpio_ext_pc3, .name = "PC3", .debug = false}, - {.pin = &gpio_ext_pc1, .name = "PC1", .debug = false}, - {.pin = &gpio_ext_pc0, .name = "PC0", .debug = false}, + // 5V: 1 + {.pin = &gpio_ext_pa7, .name = "PA7", .number = 2, .debug = false}, + {.pin = &gpio_ext_pa6, .name = "PA6", .number = 3, .debug = false}, + {.pin = &gpio_ext_pa4, .name = "PA4", .number = 4, .debug = false}, + {.pin = &gpio_ext_pb3, .name = "PB3", .number = 5, .debug = false}, + {.pin = &gpio_ext_pb2, .name = "PB2", .number = 6, .debug = false}, + {.pin = &gpio_ext_pc3, .name = "PC3", .number = 7, .debug = false}, + // GND: 8 + // Space + // 3v3: 9 + {.pin = &gpio_swclk, .name = "PA14", .number = 10, .debug = true}, + // GND: 11 + {.pin = &gpio_swdio, .name = "PA13", .number = 12, .debug = true}, + {.pin = &gpio_usart_tx, .name = "PB6", .number = 13, .debug = true}, + {.pin = &gpio_usart_rx, .name = "PB7", .number = 14, .debug = true}, + {.pin = &gpio_ext_pc1, .name = "PC1", .number = 15, .debug = false}, + {.pin = &gpio_ext_pc0, .name = "PC0", .number = 16, .debug = false}, + {.pin = &gpio_ibutton, .name = "PB14", .number = 17, .debug = true}, + // GND: 18 /* Dangerous pins, may damage hardware */ - {.pin = &gpio_usart_rx, .name = "PB7", .debug = true}, {.pin = &gpio_speaker, .name = "PB8", .debug = true}, {.pin = &gpio_infrared_tx, .name = "PB9", .debug = true}, }; -const size_t gpio_pins_count = sizeof(gpio_pins) / sizeof(GpioPinRecord); +const size_t gpio_pins_count = COUNT_OF(gpio_pins); const InputPin input_pins[] = { {.gpio = &gpio_button_up, .key = InputKeyUp, .inverted = true, .name = "Up"}, @@ -95,7 +105,7 @@ const InputPin input_pins[] = { {.gpio = &gpio_button_back, .key = InputKeyBack, .inverted = true, .name = "Back"}, }; -const size_t input_pins_count = sizeof(input_pins) / sizeof(InputPin); +const size_t input_pins_count = COUNT_OF(input_pins); static void furi_hal_resources_init_input_pins(GpioMode mode) { for(size_t i = 0; i < input_pins_count; i++) { @@ -210,24 +220,10 @@ void furi_hal_resources_init() { } int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio) { - if(gpio == &gpio_ext_pa7) - return 2; - else if(gpio == &gpio_ext_pa6) - return 3; - else if(gpio == &gpio_ext_pa4) - return 4; - else if(gpio == &gpio_ext_pb3) - return 5; - else if(gpio == &gpio_ext_pb2) - return 6; - else if(gpio == &gpio_ext_pc3) - return 7; - else if(gpio == &gpio_ext_pc1) - return 15; - else if(gpio == &gpio_ext_pc0) - return 16; - else if(gpio == &gpio_ibutton) - return 17; - else - return -1; + for(size_t i = 0; i < gpio_pins_count; i++) { + if(gpio_pins[i].pin == gpio) { + return gpio_pins[i].number; + } + } + return -1; } diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.h b/firmware/targets/f7/furi_hal/furi_hal_resources.h index 6e585c518..6ca6f9df0 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.h +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.h @@ -41,6 +41,7 @@ typedef struct { typedef struct { const GpioPin* pin; const char* name; + const uint8_t number; const bool debug; } GpioPinRecord; diff --git a/lib/drivers/bq27220.c b/lib/drivers/bq27220.c index 4a9feed9b..a3a88603d 100644 --- a/lib/drivers/bq27220.c +++ b/lib/drivers/bq27220.c @@ -54,6 +54,10 @@ static bool bq27220_parameter_check( } if(update) { + // Datasheet contains incorrect procedure for memory update, more info: + // https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/719878/bq27220-technical-reference-manual-sluubd4-is-missing-extended-data-commands-chapter + + // 2. Write the address AND the parameter data to 0x3E+ (auto increment) if(!furi_hal_i2c_write_mem( handle, BQ27220_ADDRESS, @@ -67,9 +71,12 @@ static bool bq27220_parameter_check( furi_delay_us(10000); + // 3. Calculate the check sum: 0xFF - (sum of address and data) OR 0xFF uint8_t checksum = bq27220_get_checksum(buffer, size + 2); + // 4. Write the check sum to 0x60 and the total length of (address + parameter data + check sum + length) to 0x61 buffer[0] = checksum; - buffer[1] = 4 + size; // TODO FL-3519: why 4? + // 2 bytes address, `size` bytes data, 1 byte check sum, 1 byte length + buffer[1] = 2 + size + 1 + 1; if(!furi_hal_i2c_write_mem( handle, BQ27220_ADDRESS, CommandMACDataSum, buffer, 2, BQ27220_I2C_TIMEOUT)) { FURI_LOG_I(TAG, "CRC write failed"); From 7531e18020b4f2b67b60950c841dc8e282d97d12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Fri, 1 Sep 2023 11:00:40 +0900 Subject: [PATCH 07/11] Move roadmap link to readme (#3014) Co-authored-by: hedger --- ReadMe.md | 4 ++++ documentation/RoadMap.md | 46 ---------------------------------------- 2 files changed, 4 insertions(+), 46 deletions(-) delete mode 100644 documentation/RoadMap.md diff --git a/ReadMe.md b/ReadMe.md index bbaf9603e..dcf39c3ae 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -36,6 +36,10 @@ Finally, open a [Pull Request](https://github.com/flipperdevices/flipperzero-fir Flipper Zero Firmware is written in C, with some bits and pieces written in C++ and armv7m assembly languages. An intermediate level of C knowledge is recommended for comfortable programming. C, C++, and armv7m assembly languages are supported for Flipper applications. +# Firmware RoadMap + +[Firmware RoadMap Miro Board](https://miro.com/app/board/uXjVO_3D6xU=/) + ## Requirements Supported development platforms: diff --git a/documentation/RoadMap.md b/documentation/RoadMap.md deleted file mode 100644 index 658bb2086..000000000 --- a/documentation/RoadMap.md +++ /dev/null @@ -1,46 +0,0 @@ -# RoadMap - -# Where we are now (0.x.x branch) - -Our goal for the 0.x.x branch is to build an API and apps that are stable and usable. The first public release in this branch is 0.43.1. - -## What's already implemented - -**System and HAL** - -- Furi Core -- Furi HAL -- Loading applications from SD - -**Applications** - -- SubGhz: all most common protocols, reading RAW for everything else -- 125kHz RFID: all most common protocols -- NFC: reading/emulating MIFARE Ultralight, reading MIFARE Classic and DESFire, basic EMV, and basic NFC-B/F/V -- Infrared: all most common RC protocols, RAW format for everything else -- GPIO: UART bridge, basic GPIO controls -- iButton: DS1990, Cyfral, Metakom -- Bad USB: full USB Rubber Ducky support, some extras for Windows Alt codes -- U2F: full U2F specification support - -**External applications** - -- Bluetooth -- Snake game - -# Where we're going (Version 1) - -The main goal for 1.0.0 is to provide the first stable version for both Users and Developers. - -## What we're planning to implement in 1.0.0 - -- More protocols (gathering feedback) -- User documentation (work in progress) -- FuriHal: deep sleep mode, stable API, examples, documentation (work in progress) -- Application improvements (a ton of things that we want to add and improve that are too numerous to list here) - -## When will it happen, and where can I see the progress? - -Release 1.0.0 will likely happen around the end of 2023Q1. - -You can track the development progress in our public Miro board: https://miro.com/app/board/uXjVO_3D6xU=/?moveToWidget=3458764522498020058&cot=14 From d8d2b360cb819fedef198427b9d22adab5e0da8d Mon Sep 17 00:00:00 2001 From: suaveolent <2163625+suaveolent@users.noreply.github.com> Date: Fri, 1 Sep 2023 04:22:29 +0200 Subject: [PATCH 08/11] Add support for Mifare Classic 4k SAK 0x38 ATQA 0x02, 0x04, 0x08 (#3009) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: suaveolent Co-authored-by: あく --- lib/nfc/protocols/mifare_classic.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index 011747d59..a72d4aac0 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -381,7 +381,9 @@ bool mf_classic_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { } else if((ATQA0 == 0x01) && (ATQA1 == 0x0F) && (SAK == 0x01)) { //skylanders support return true; - } else if((ATQA0 == 0x42 || ATQA0 == 0x02) && (SAK == 0x18)) { + } else if( + ((ATQA0 == 0x42 || ATQA0 == 0x02) && (SAK == 0x18)) || + ((ATQA0 == 0x02 || ATQA0 == 0x04 || ATQA0 == 0x08) && (SAK == 0x38))) { return true; } else { return false; @@ -393,13 +395,17 @@ MfClassicType mf_classic_get_classic_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t if((ATQA0 == 0x44 || ATQA0 == 0x04)) { if((SAK == 0x08 || SAK == 0x88)) { return MfClassicType1k; + } else if((SAK == 0x38)) { + return MfClassicType4k; } else if(SAK == 0x09) { return MfClassicTypeMini; } } else if((ATQA0 == 0x01) && (ATQA1 == 0x0F) && (SAK == 0x01)) { //skylanders support return MfClassicType1k; - } else if((ATQA0 == 0x42 || ATQA0 == 0x02) && (SAK == 0x18)) { + } else if( + ((ATQA0 == 0x42 || ATQA0 == 0x02) && (SAK == 0x18)) || + ((ATQA0 == 0x02 || ATQA0 == 0x08) && (SAK == 0x38))) { return MfClassicType4k; } return MfClassicType1k; From 5eeb672dd454659ea2f1d218e136ebb9f321cebf Mon Sep 17 00:00:00 2001 From: hedger Date: Fri, 1 Sep 2023 06:09:48 +0300 Subject: [PATCH 09/11] github: workflow trigger optimizations (#3030) --- .github/workflows/build.yml | 72 +----------------- .github/workflows/build_compact.yml | 75 +++++++++++++++++++ .../workflows/lint_and_submodule_check.yml | 7 +- .github/workflows/merge_report.yml | 2 +- .github/workflows/pvs_studio.yml | 2 - .github/workflows/reindex.yml | 2 +- 6 files changed, 79 insertions(+), 81 deletions(-) create mode 100644 .github/workflows/build_compact.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bd85858a3..07b219712 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,7 +15,7 @@ env: jobs: main: - runs-on: [self-hosted,FlipperZeroShell] + runs-on: [self-hosted, FlipperZeroShell] steps: - name: 'Wipe workspace' run: find ./ -mount -maxdepth 1 -exec rm -rf {} \; @@ -37,7 +37,6 @@ jobs: TYPE="other" fi python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE" || cat "${{ github.event_path }}" - echo random_hash=$(openssl rand -base64 40 | shasum -a 256 | awk '{print $1}') >> $GITHUB_OUTPUT echo "event_type=$TYPE" >> $GITHUB_OUTPUT - name: 'Check API versions' @@ -149,72 +148,3 @@ jobs: - [📥 DFU file](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-full-${{steps.names.outputs.suffix}}.dfu) - [☁️ Web/App updater](https://lab.flipper.net/?url=https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz&channel=${{steps.names.outputs.branch_name}}&version=${{steps.names.outputs.commit_sha}}) edit-mode: replace - - compact: - if: ${{ !startsWith(github.ref, 'refs/tags') }} - runs-on: [self-hosted,FlipperZeroShell] - strategy: - matrix: - target: [f7, f18] - steps: - - name: 'Wipe workspace' - run: find ./ -mount -maxdepth 1 -exec rm -rf {} \; - - - name: 'Checkout code' - uses: actions/checkout@v3 - with: - fetch-depth: 1 - submodules: false - ref: ${{ github.event.pull_request.head.sha }} - - - name: 'Get commit details' - run: | - if [[ ${{ github.event_name }} == 'pull_request' ]]; then - TYPE="pull" - elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then - TYPE="tag" - else - TYPE="other" - fi - python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE" || cat "${{ github.event_path }}" - - - name: 'Build the firmware' - id: build-fw - run: | - set -e - TARGET="$(echo '${{ matrix.target }}' | sed 's/f//')"; \ - ./fbt TARGET_HW=$TARGET DEBUG=0 COMPACT=1 fap_dist updater_package - echo "sdk-file=$(ls dist/${{ matrix.target }}-*/flipper-z-${{ matrix.target }}-sdk-*.zip)" >> $GITHUB_OUTPUT - echo "hw-target-code=$TARGET" >> $GITHUB_OUTPUT - - - name: Deploy uFBT with SDK - uses: flipperdevices/flipperzero-ufbt-action@v0.1.0 - with: - task: setup - sdk-file: ${{ steps.build-fw.outputs.sdk-file }} - sdk-hw-target: ${{ steps.build-fw.outputs.hw-target-code }} - - - name: Build test app with SDK - run: | - mkdir testapp - cd testapp - ufbt create APPID=testapp - ufbt - - - name: Build example & external apps with uFBT - run: | - for appdir in 'applications/examples'; do - for app in $(find "$appdir" -maxdepth 1 -mindepth 1 -type d); do - pushd $app - TARGETS_FAM=$(grep "targets" application.fam || echo "${{ matrix.target }}") - if ! grep -q "${{ matrix.target }}" <<< $TARGETS_FAM ; then - echo Skipping unsupported app: $app - popd - continue - fi - echo Building $app - ufbt - popd - done - done - diff --git a/.github/workflows/build_compact.yml b/.github/workflows/build_compact.yml new file mode 100644 index 000000000..705888a41 --- /dev/null +++ b/.github/workflows/build_compact.yml @@ -0,0 +1,75 @@ +name: 'Compact build' + +on: + pull_request: + +env: + FBT_TOOLCHAIN_PATH: /runner/_work + +jobs: + compact: + runs-on: [self-hosted, FlipperZeroShell] + strategy: + matrix: + target: [f7, f18] + steps: + - name: 'Wipe workspace' + run: find ./ -mount -maxdepth 1 -exec rm -rf {} \; + + - name: 'Checkout code' + uses: actions/checkout@v3 + with: + fetch-depth: 1 + submodules: false + ref: ${{ github.event.pull_request.head.sha }} + + - name: 'Get commit details' + run: | + if [[ ${{ github.event_name }} == 'pull_request' ]]; then + TYPE="pull" + elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then + TYPE="tag" + else + TYPE="other" + fi + python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE" || cat "${{ github.event_path }}" + + - name: 'Build the firmware' + id: build-fw + run: | + set -e + TARGET="$(echo '${{ matrix.target }}' | sed 's/f//')"; \ + ./fbt TARGET_HW=$TARGET DEBUG=0 COMPACT=1 fap_dist updater_package + echo "sdk-file=$(ls dist/${{ matrix.target }}-*/flipper-z-${{ matrix.target }}-sdk-*.zip)" >> $GITHUB_OUTPUT + echo "hw-target-code=$TARGET" >> $GITHUB_OUTPUT + + - name: Deploy uFBT with SDK + uses: flipperdevices/flipperzero-ufbt-action@v0.1.0 + with: + task: setup + sdk-file: ${{ steps.build-fw.outputs.sdk-file }} + sdk-hw-target: ${{ steps.build-fw.outputs.hw-target-code }} + + - name: Build test app with SDK + run: | + mkdir testapp + cd testapp + ufbt create APPID=testapp + ufbt + + - name: Build example & external apps with uFBT + run: | + for appdir in 'applications/examples'; do + for app in $(find "$appdir" -maxdepth 1 -mindepth 1 -type d); do + pushd $app + TARGETS_FAM=$(grep "targets" application.fam || echo "${{ matrix.target }}") + if ! grep -q "${{ matrix.target }}" <<< $TARGETS_FAM ; then + echo Skipping unsupported app: $app + popd + continue + fi + echo Building $app + ufbt + popd + done + done diff --git a/.github/workflows/lint_and_submodule_check.yml b/.github/workflows/lint_and_submodule_check.yml index b85409ecd..62e02b8a4 100644 --- a/.github/workflows/lint_and_submodule_check.yml +++ b/.github/workflows/lint_and_submodule_check.yml @@ -1,11 +1,6 @@ name: 'Lint sources & check submodule integrity' on: - push: - branches: - - dev - tags: - - '*' pull_request: env: @@ -15,7 +10,7 @@ env: jobs: lint_sources_check_submodules: - runs-on: [self-hosted,FlipperZeroShell] + runs-on: [self-hosted, FlipperZeroShell] steps: - name: 'Wipe workspace' run: find ./ -mount -maxdepth 1 -exec rm -rf {} \; diff --git a/.github/workflows/merge_report.yml b/.github/workflows/merge_report.yml index 020166666..fedc4b87f 100644 --- a/.github/workflows/merge_report.yml +++ b/.github/workflows/merge_report.yml @@ -10,7 +10,7 @@ env: jobs: merge_report: - runs-on: [self-hosted,FlipperZeroShell] + runs-on: [self-hosted, FlipperZeroShell] steps: - name: 'Wipe workspace' run: find ./ -mount -maxdepth 1 -exec rm -rf {} \; diff --git a/.github/workflows/pvs_studio.yml b/.github/workflows/pvs_studio.yml index cb5b50278..24964a309 100644 --- a/.github/workflows/pvs_studio.yml +++ b/.github/workflows/pvs_studio.yml @@ -4,8 +4,6 @@ on: push: branches: - dev - tags: - - '*' pull_request: env: diff --git a/.github/workflows/reindex.yml b/.github/workflows/reindex.yml index 5645f609b..82cb04680 100644 --- a/.github/workflows/reindex.yml +++ b/.github/workflows/reindex.yml @@ -7,7 +7,7 @@ on: jobs: reindex: name: 'Reindex updates' - runs-on: [self-hosted,FlipperZeroShell] + runs-on: [self-hosted, FlipperZeroShell] steps: - name: Trigger reindex run: | From e5fdb2e069698c441af69e03d876034f9c05c559 Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Fri, 1 Sep 2023 13:54:12 +0900 Subject: [PATCH 10/11] [FL-3314] Disconnect from BLE on protobuf error (#2955) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Disconnect from BLE on protobuf error * Set profile instead of disconnecting and add logging Co-authored-by: あく --- applications/services/rpc/rpc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/applications/services/rpc/rpc.c b/applications/services/rpc/rpc.c index b3ed4417c..3e9665ad8 100644 --- a/applications/services/rpc/rpc.c +++ b/applications/services/rpc/rpc.c @@ -15,6 +15,8 @@ #include #include +#include + #define TAG "RpcSrv" typedef enum { @@ -316,6 +318,15 @@ static int32_t rpc_session_worker(void* context) { session->closed_callback(session->context); } furi_mutex_release(session->callbacks_mutex); + + if(session->owner == RpcOwnerBle) { + // Disconnect BLE session + FURI_LOG_E("RPC", "BLE session closed due to a decode error"); + Bt* bt = furi_record_open(RECORD_BT); + bt_set_profile(bt, BtProfileSerial); + furi_record_close(RECORD_BT); + FURI_LOG_E("RPC", "Finished disconnecting the BLE session"); + } } } From 52b59662627254ae5ccde6201b5c4921573fc769 Mon Sep 17 00:00:00 2001 From: Max <66625166+m1-ins@users.noreply.github.com> Date: Fri, 1 Sep 2023 06:57:49 +0100 Subject: [PATCH 11/11] Add File Naming setting for more detailed naming (#3002) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added filename mode setting * added furi_flag checks for when filename_mode is set * changed naming for ibutton, lfrfid and subghz * requested changes from PR * Lib: gather all naming bits and pieces under name generator module. Properly bump api version. FuriHal: fix RTC flag enum. * PR requested changes * bug fix for arg type * added functionality for other application scenes * Lib: cleanup name generator API, simplify usage. Sync API symbols. * Lib: proper size type in name_generator. Cleanup. * FuriHal: cleanup rtc api usage across firmware Co-authored-by: あく --- applications/main/ibutton/ibutton.c | 3 +- applications/main/ibutton/ibutton_i.h | 3 +- .../ibutton/scenes/ibutton_scene_save_name.c | 11 +-- .../scenes/infrared_scene_universal_ac.c | 1 - applications/main/lfrfid/lfrfid.c | 10 ++- applications/main/lfrfid/lfrfid_i.h | 5 +- .../lfrfid/scenes/lfrfid_scene_save_name.c | 9 ++- applications/main/nfc/nfc.c | 6 +- .../main/nfc/scenes/nfc_scene_save_name.c | 8 +- .../subghz/scenes/subghz_scene_read_raw.c | 6 +- .../subghz/scenes/subghz_scene_save_name.c | 13 +++- applications/main/subghz/subghz_i.c | 9 ++- applications/services/gui/canvas.c | 1 - applications/services/gui/view_port.c | 1 - .../settings/system/system_settings.c | 21 ++++++ firmware/targets/f18/api_symbols.csv | 8 +- firmware/targets/f7/api_symbols.csv | 8 +- .../targets/furi_hal_include/furi_hal_rtc.h | 1 + lib/nfc/nfc_device.c | 8 +- lib/nfc/nfc_device.h | 3 +- lib/subghz/protocols/raw.c | 3 +- lib/subghz/types.h | 3 +- lib/toolbox/SConscript | 2 +- lib/toolbox/name_generator.c | 75 +++++++++++++++++++ lib/toolbox/name_generator.h | 35 +++++++++ lib/toolbox/random_name.c | 35 --------- lib/toolbox/random_name.h | 17 ----- 27 files changed, 207 insertions(+), 98 deletions(-) create mode 100644 lib/toolbox/name_generator.c create mode 100644 lib/toolbox/name_generator.h delete mode 100644 lib/toolbox/random_name.c delete mode 100644 lib/toolbox/random_name.h diff --git a/applications/main/ibutton/ibutton.c b/applications/main/ibutton/ibutton.c index ad5b233b5..67873690c 100644 --- a/applications/main/ibutton/ibutton.c +++ b/applications/main/ibutton/ibutton.c @@ -195,7 +195,8 @@ bool ibutton_load_key(iButton* ibutton) { bool ibutton_select_and_load_key(iButton* ibutton) { DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, IBUTTON_APP_EXTENSION, &I_ibutt_10px); + dialog_file_browser_set_basic_options( + &browser_options, IBUTTON_APP_FILENAME_EXTENSION, &I_ibutt_10px); browser_options.base_path = IBUTTON_APP_FOLDER; if(furi_string_empty(ibutton->file_path)) { diff --git a/applications/main/ibutton/ibutton_i.h b/applications/main/ibutton/ibutton_i.h index 509279210..077b14807 100644 --- a/applications/main/ibutton/ibutton_i.h +++ b/applications/main/ibutton/ibutton_i.h @@ -29,7 +29,8 @@ #include "scenes/ibutton_scene.h" #define IBUTTON_APP_FOLDER ANY_PATH("ibutton") -#define IBUTTON_APP_EXTENSION ".ibtn" +#define IBUTTON_APP_FILENAME_PREFIX "iBtn" +#define IBUTTON_APP_FILENAME_EXTENSION ".ibtn" #define IBUTTON_KEY_NAME_SIZE 22 diff --git a/applications/main/ibutton/scenes/ibutton_scene_save_name.c b/applications/main/ibutton/scenes/ibutton_scene_save_name.c index 7bd49df83..e6236dc35 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_save_name.c +++ b/applications/main/ibutton/scenes/ibutton_scene_save_name.c @@ -1,6 +1,6 @@ #include "../ibutton_i.h" -#include +#include #include #include @@ -17,7 +17,8 @@ void ibutton_scene_save_name_on_enter(void* context) { const bool is_new_file = furi_string_empty(ibutton->file_path); if(is_new_file) { - set_random_name(ibutton->key_name, IBUTTON_KEY_NAME_SIZE); + name_generator_make_auto( + ibutton->key_name, IBUTTON_KEY_NAME_SIZE, IBUTTON_APP_FILENAME_PREFIX); } text_input_set_header_text(text_input, "Name the key"); @@ -29,8 +30,8 @@ void ibutton_scene_save_name_on_enter(void* context) { IBUTTON_KEY_NAME_SIZE, is_new_file); - ValidatorIsFile* validator_is_file = - validator_is_file_alloc_init(IBUTTON_APP_FOLDER, IBUTTON_APP_EXTENSION, ibutton->key_name); + ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( + IBUTTON_APP_FOLDER, IBUTTON_APP_FILENAME_EXTENSION, ibutton->key_name); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewTextInput); @@ -48,7 +49,7 @@ bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) { "%s/%s%s", IBUTTON_APP_FOLDER, ibutton->key_name, - IBUTTON_APP_EXTENSION); + IBUTTON_APP_FILENAME_EXTENSION); if(ibutton_save_key(ibutton)) { scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveSuccess); diff --git a/applications/main/infrared/scenes/infrared_scene_universal_ac.c b/applications/main/infrared/scenes/infrared_scene_universal_ac.c index cbb09a525..5f762d122 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_ac.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_ac.c @@ -1,7 +1,6 @@ #include "../infrared_i.h" #include "common/infrared_scene_universal_common.h" -#include void infrared_scene_universal_ac_on_enter(void* context) { infrared_scene_universal_common_on_enter(context); diff --git a/applications/main/lfrfid/lfrfid.c b/applications/main/lfrfid/lfrfid.c index aa7510a90..2bef08df2 100644 --- a/applications/main/lfrfid/lfrfid.c +++ b/applications/main/lfrfid/lfrfid.c @@ -215,13 +215,16 @@ bool lfrfid_save_key(LfRfid* app) { lfrfid_make_app_folder(app); - if(furi_string_end_with(app->file_path, LFRFID_APP_EXTENSION)) { + if(furi_string_end_with(app->file_path, LFRFID_APP_FILENAME_EXTENSION)) { size_t filename_start = furi_string_search_rchar(app->file_path, '/'); furi_string_left(app->file_path, filename_start); } furi_string_cat_printf( - app->file_path, "/%s%s", furi_string_get_cstr(app->file_name), LFRFID_APP_EXTENSION); + app->file_path, + "/%s%s", + furi_string_get_cstr(app->file_name), + LFRFID_APP_FILENAME_EXTENSION); result = lfrfid_save_key_data(app, app->file_path); return result; @@ -231,7 +234,8 @@ bool lfrfid_load_key_from_file_select(LfRfid* app) { furi_assert(app); DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, LFRFID_APP_EXTENSION, &I_125_10px); + dialog_file_browser_set_basic_options( + &browser_options, LFRFID_APP_FILENAME_EXTENSION, &I_125_10px); browser_options.base_path = LFRFID_APP_FOLDER; // Input events and views are managed by file_browser diff --git a/applications/main/lfrfid/lfrfid_i.h b/applications/main/lfrfid/lfrfid_i.h index 72b061930..d94a5f865 100644 --- a/applications/main/lfrfid/lfrfid_i.h +++ b/applications/main/lfrfid/lfrfid_i.h @@ -40,8 +40,9 @@ #define LFRFID_APP_FOLDER ANY_PATH("lfrfid") #define LFRFID_SD_FOLDER EXT_PATH("lfrfid") -#define LFRFID_APP_EXTENSION ".rfid" -#define LFRFID_APP_SHADOW_EXTENSION ".shd" +#define LFRFID_APP_FILENAME_PREFIX "RFID" +#define LFRFID_APP_FILENAME_EXTENSION ".rfid" +#define LFRFID_APP_SHADOW_FILENAME_EXTENSION ".shd" #define LFRFID_APP_RAW_ASK_EXTENSION ".ask.raw" #define LFRFID_APP_RAW_PSK_EXTENSION ".psk.raw" diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_save_name.c b/applications/main/lfrfid/scenes/lfrfid_scene_save_name.c index 771f2f603..3a38e213d 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_save_name.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_save_name.c @@ -1,6 +1,6 @@ -#include #include "../lfrfid_i.h" #include +#include void lfrfid_scene_save_name_on_enter(void* context) { LfRfid* app = context; @@ -11,7 +11,10 @@ void lfrfid_scene_save_name_on_enter(void* context) { bool key_name_is_empty = furi_string_empty(app->file_name); if(key_name_is_empty) { furi_string_set(app->file_path, LFRFID_APP_FOLDER); - set_random_name(app->text_store, LFRFID_TEXT_STORE_SIZE); + + name_generator_make_auto( + app->text_store, LFRFID_TEXT_STORE_SIZE, LFRFID_APP_FILENAME_PREFIX); + furi_string_set(folder_path, LFRFID_APP_FOLDER); } else { lfrfid_text_store_set(app, "%s", furi_string_get_cstr(app->file_name)); @@ -31,7 +34,7 @@ void lfrfid_scene_save_name_on_enter(void* context) { ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( furi_string_get_cstr(folder_path), - LFRFID_APP_EXTENSION, + LFRFID_APP_FILENAME_EXTENSION, furi_string_get_cstr(app->file_name)); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); diff --git a/applications/main/nfc/nfc.c b/applications/main/nfc/nfc.c index 56d98a8c6..4ac793b5b 100644 --- a/applications/main/nfc/nfc.c +++ b/applications/main/nfc/nfc.c @@ -223,7 +223,11 @@ void nfc_blink_stop(Nfc* nfc) { bool nfc_save_file(Nfc* nfc) { furi_string_printf( - nfc->dev->load_path, "%s/%s%s", NFC_APP_FOLDER, nfc->dev->dev_name, NFC_APP_EXTENSION); + nfc->dev->load_path, + "%s/%s%s", + NFC_APP_FOLDER, + nfc->dev->dev_name, + NFC_APP_FILENAME_EXTENSION); bool file_saved = nfc_device_save(nfc->dev, furi_string_get_cstr(nfc->dev->load_path)); return file_saved; } diff --git a/applications/main/nfc/scenes/nfc_scene_save_name.c b/applications/main/nfc/scenes/nfc_scene_save_name.c index a7b97aac0..b18e17633 100644 --- a/applications/main/nfc/scenes/nfc_scene_save_name.c +++ b/applications/main/nfc/scenes/nfc_scene_save_name.c @@ -1,5 +1,5 @@ #include "../nfc_i.h" -#include +#include #include #include #include @@ -17,7 +17,7 @@ void nfc_scene_save_name_on_enter(void* context) { TextInput* text_input = nfc->text_input; bool dev_name_empty = false; if(!strcmp(nfc->dev->dev_name, "")) { - set_random_name(nfc->text_store, sizeof(nfc->text_store)); + name_generator_make_auto(nfc->text_store, NFC_DEV_NAME_MAX_LEN, NFC_APP_FILENAME_PREFIX); dev_name_empty = true; } else { nfc_text_store_set(nfc, nfc->dev->dev_name); @@ -34,14 +34,14 @@ void nfc_scene_save_name_on_enter(void* context) { FuriString* folder_path; folder_path = furi_string_alloc(); - if(furi_string_end_with(nfc->dev->load_path, NFC_APP_EXTENSION)) { + if(furi_string_end_with(nfc->dev->load_path, NFC_APP_FILENAME_EXTENSION)) { path_extract_dirname(furi_string_get_cstr(nfc->dev->load_path), folder_path); } else { furi_string_set(folder_path, NFC_APP_FOLDER); } ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( - furi_string_get_cstr(folder_path), NFC_APP_EXTENSION, nfc->dev->dev_name); + furi_string_get_cstr(folder_path), NFC_APP_FILENAME_EXTENSION, nfc->dev->dev_name); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput); diff --git a/applications/main/subghz/scenes/subghz_scene_read_raw.c b/applications/main/subghz/scenes/subghz_scene_read_raw.c index 58e4b0429..bbcc43256 100644 --- a/applications/main/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_read_raw.c @@ -239,7 +239,11 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { FuriString* temp_str = furi_string_alloc(); furi_string_printf( - temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, RAW_FILE_NAME, SUBGHZ_APP_EXTENSION); + temp_str, + "%s/%s%s", + SUBGHZ_RAW_FOLDER, + RAW_FILE_NAME, + SUBGHZ_APP_FILENAME_EXTENSION); subghz_protocol_raw_gen_fff_data( subghz_txrx_get_fff_data(subghz->txrx), furi_string_get_cstr(temp_str), diff --git a/applications/main/subghz/scenes/subghz_scene_save_name.c b/applications/main/subghz/scenes/subghz_scene_save_name.c index 86eddfe8e..394dda89e 100644 --- a/applications/main/subghz/scenes/subghz_scene_save_name.c +++ b/applications/main/subghz/scenes/subghz_scene_save_name.c @@ -1,10 +1,10 @@ #include "../subghz_i.h" #include "subghz/types.h" -#include #include "../helpers/subghz_custom_event.h" #include #include #include +#include #define MAX_TEXT_INPUT_LEN 22 @@ -40,7 +40,9 @@ void subghz_scene_save_name_on_enter(void* context) { if(!subghz_path_is_file(subghz->file_path)) { char file_name_buf[SUBGHZ_MAX_LEN_NAME] = {0}; - set_random_name(file_name_buf, SUBGHZ_MAX_LEN_NAME); + + name_generator_make_auto(file_name_buf, SUBGHZ_MAX_LEN_NAME, SUBGHZ_APP_FILENAME_PREFIX); + furi_string_set(file_name, file_name_buf); furi_string_set(subghz->file_path, SUBGHZ_APP_FOLDER); //highlighting the entire filename by default @@ -71,7 +73,7 @@ void subghz_scene_save_name_on_enter(void* context) { dev_name_empty); ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( - furi_string_get_cstr(subghz->file_path), SUBGHZ_APP_EXTENSION, ""); + furi_string_get_cstr(subghz->file_path), SUBGHZ_APP_FILENAME_EXTENSION, ""); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); furi_string_free(file_name); @@ -94,7 +96,10 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { if(event.event == SubGhzCustomEventSceneSaveName) { if(strcmp(subghz->file_name_tmp, "") != 0) { furi_string_cat_printf( - subghz->file_path, "/%s%s", subghz->file_name_tmp, SUBGHZ_APP_EXTENSION); + subghz->file_path, + "/%s%s", + subghz->file_name_tmp, + SUBGHZ_APP_FILENAME_EXTENSION); if(subghz_path_is_file(subghz->file_path_tmp)) { if(!subghz_rename_file(subghz)) { return false; diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index 9ff618371..c03efe5e5 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -238,7 +238,7 @@ bool subghz_get_next_name_file(SubGhz* subghz, uint8_t max_len) { storage, furi_string_get_cstr(file_path), furi_string_get_cstr(file_name), - SUBGHZ_APP_EXTENSION, + SUBGHZ_APP_FILENAME_EXTENSION, file_name, max_len); @@ -247,7 +247,7 @@ bool subghz_get_next_name_file(SubGhz* subghz, uint8_t max_len) { "%s/%s%s", furi_string_get_cstr(file_path), furi_string_get_cstr(file_name), - SUBGHZ_APP_EXTENSION); + SUBGHZ_APP_FILENAME_EXTENSION); furi_string_set(subghz->file_path, temp_str); res = true; } @@ -320,7 +320,8 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { FuriString* file_path = furi_string_alloc(); DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, SUBGHZ_APP_EXTENSION, &I_sub1_10px); + dialog_file_browser_set_basic_options( + &browser_options, SUBGHZ_APP_FILENAME_EXTENSION, &I_sub1_10px); browser_options.base_path = SUBGHZ_APP_FOLDER; // Input events and views are managed by file_select @@ -394,7 +395,7 @@ void subghz_file_name_clear(SubGhz* subghz) { } bool subghz_path_is_file(FuriString* path) { - return furi_string_end_with(path, SUBGHZ_APP_EXTENSION); + return furi_string_end_with(path, SUBGHZ_APP_FILENAME_EXTENSION); } void subghz_lock(SubGhz* subghz) { diff --git a/applications/services/gui/canvas.c b/applications/services/gui/canvas.c index 6e35dcffb..37edc5d33 100644 --- a/applications/services/gui/canvas.c +++ b/applications/services/gui/canvas.c @@ -4,7 +4,6 @@ #include #include -#include #include #include diff --git a/applications/services/gui/view_port.c b/applications/services/gui/view_port.c index 0f300c168..6723a777b 100644 --- a/applications/services/gui/view_port.c +++ b/applications/services/gui/view_port.c @@ -2,7 +2,6 @@ #include #include -#include #include "gui.h" #include "gui_i.h" diff --git a/applications/settings/system/system_settings.c b/applications/settings/system/system_settings.c index dd3c0dc6b..d19b4747b 100644 --- a/applications/settings/system/system_settings.c +++ b/applications/settings/system/system_settings.c @@ -153,6 +153,21 @@ static void sleep_method_changed(VariableItem* item) { } } +const char* const filename_scheme[] = { + "Default", + "Detailed", +}; + +static void filename_scheme_changed(VariableItem* item) { + uint8_t index = variable_item_get_current_value_index(item); + variable_item_set_current_value_text(item, filename_scheme[index]); + if(index) { + furi_hal_rtc_set_flag(FuriHalRtcFlagDetailedFilename); + } else { + furi_hal_rtc_reset_flag(FuriHalRtcFlagDetailedFilename); + } +} + static uint32_t system_settings_exit(void* context) { UNUSED(context); return VIEW_NONE; @@ -236,6 +251,12 @@ SystemSettings* system_settings_alloc() { variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, sleep_method[value_index]); + item = variable_item_list_add( + app->var_item_list, "File Naming", COUNT_OF(filename_scheme), filename_scheme_changed, app); + value_index = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDetailedFilename) ? 1 : 0; + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, filename_scheme[value_index]); + view_set_previous_callback( variable_item_list_get_view(app->var_item_list), system_settings_exit); view_dispatcher_add_view( diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index a61679bca..a26db8823 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,35.1,, +Version,+,36.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -172,10 +172,10 @@ Header,+,lib/toolbox/hex.h,, Header,+,lib/toolbox/manchester_decoder.h,, Header,+,lib/toolbox/manchester_encoder.h,, Header,+,lib/toolbox/md5.h,, +Header,+,lib/toolbox/name_generator.h,, Header,+,lib/toolbox/path.h,, Header,+,lib/toolbox/pretty_format.h,, Header,+,lib/toolbox/protocols/protocol_dict.h,, -Header,+,lib/toolbox/random_name.h,, Header,+,lib/toolbox/saved_struct.h,, Header,+,lib/toolbox/sha256.h,, Header,+,lib/toolbox/stream/buffered_file_stream.h,, @@ -1705,6 +1705,9 @@ Function,-,music_worker_set_callback,void,"MusicWorker*, MusicWorkerCallback, vo Function,-,music_worker_set_volume,void,"MusicWorker*, float" Function,-,music_worker_start,void,MusicWorker* Function,-,music_worker_stop,void,MusicWorker* +Function,+,name_generator_make_auto,void,"char*, size_t, const char*" +Function,+,name_generator_make_detailed,void,"char*, size_t, const char*" +Function,+,name_generator_make_random,void,"char*, size_t" Function,-,nan,double,const char* Function,-,nanf,float,const char* Function,-,nanl,long double,const char* @@ -1925,7 +1928,6 @@ Function,-,serial_svc_set_rpc_status,void,SerialServiceRpcStatus Function,-,serial_svc_start,void, Function,-,serial_svc_stop,void, Function,-,serial_svc_update_tx,_Bool,"uint8_t*, uint16_t" -Function,+,set_random_name,void,"char*, uint8_t" Function,-,setbuf,void,"FILE*, char*" Function,-,setbuffer,void,"FILE*, char*, int" Function,-,setenv,int,"const char*, const char*, int" diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 8baec5a8d..6ad88d9b8 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,+,35.1,, +Version,+,36.0,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, @@ -213,10 +213,10 @@ Header,+,lib/toolbox/hex.h,, Header,+,lib/toolbox/manchester_decoder.h,, Header,+,lib/toolbox/manchester_encoder.h,, Header,+,lib/toolbox/md5.h,, +Header,+,lib/toolbox/name_generator.h,, Header,+,lib/toolbox/path.h,, Header,+,lib/toolbox/pretty_format.h,, Header,+,lib/toolbox/protocols/protocol_dict.h,, -Header,+,lib/toolbox/random_name.h,, Header,+,lib/toolbox/saved_struct.h,, Header,+,lib/toolbox/sha256.h,, Header,+,lib/toolbox/stream/buffered_file_stream.h,, @@ -2090,6 +2090,9 @@ Function,-,music_worker_set_callback,void,"MusicWorker*, MusicWorkerCallback, vo Function,-,music_worker_set_volume,void,"MusicWorker*, float" Function,-,music_worker_start,void,MusicWorker* Function,-,music_worker_stop,void,MusicWorker* +Function,+,name_generator_make_auto,void,"char*, size_t, const char*" +Function,+,name_generator_make_detailed,void,"char*, size_t, const char*" +Function,+,name_generator_make_random,void,"char*, size_t" Function,-,nan,double,const char* Function,-,nanf,float,const char* Function,-,nanl,long double,const char* @@ -2535,7 +2538,6 @@ Function,-,serial_svc_set_rpc_status,void,SerialServiceRpcStatus Function,-,serial_svc_start,void, Function,-,serial_svc_stop,void, Function,-,serial_svc_update_tx,_Bool,"uint8_t*, uint16_t" -Function,+,set_random_name,void,"char*, uint8_t" Function,-,setbuf,void,"FILE*, char*" Function,-,setbuffer,void,"FILE*, char*, int" Function,-,setenv,int,"const char*, const char*, int" diff --git a/firmware/targets/furi_hal_include/furi_hal_rtc.h b/firmware/targets/furi_hal_include/furi_hal_rtc.h index 186d22f07..c457b6903 100644 --- a/firmware/targets/furi_hal_include/furi_hal_rtc.h +++ b/firmware/targets/furi_hal_include/furi_hal_rtc.h @@ -32,6 +32,7 @@ typedef enum { FuriHalRtcFlagHandOrient = (1 << 4), FuriHalRtcFlagLegacySleep = (1 << 5), FuriHalRtcFlagStealthMode = (1 << 6), + FuriHalRtcFlagDetailedFilename = (1 << 7), } FuriHalRtcFlag; typedef enum { diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index 2c92b5bf3..c5c8b4338 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -1360,7 +1360,7 @@ void nfc_device_set_name(NfcDevice* dev, const char* name) { static void nfc_device_get_path_without_ext(FuriString* orig_path, FuriString* shadow_path) { // TODO: this won't work if there is ".nfc" anywhere in the path other than // at the end - size_t ext_start = furi_string_search(orig_path, NFC_APP_EXTENSION); + size_t ext_start = furi_string_search(orig_path, NFC_APP_FILENAME_EXTENSION); furi_string_set_n(shadow_path, orig_path, 0, ext_start); } @@ -1587,7 +1587,7 @@ bool nfc_file_select(NfcDevice* dev) { // Input events and views are managed by file_browser const DialogsFileBrowserOptions browser_options = { - .extension = NFC_APP_EXTENSION, + .extension = NFC_APP_FILENAME_EXTENSION, .skip_assets = true, .hide_dot_files = true, .icon = &I_Nfc_10px, @@ -1659,7 +1659,7 @@ bool nfc_device_delete(NfcDevice* dev, bool use_load_path) { "%s/%s%s", furi_string_get_cstr(dev->folder), dev->dev_name, - NFC_APP_EXTENSION); + NFC_APP_FILENAME_EXTENSION); } if(!storage_simply_remove(dev->storage, furi_string_get_cstr(file_path))) break; // Delete shadow file if it exists @@ -1717,7 +1717,7 @@ bool nfc_device_restore(NfcDevice* dev, bool use_load_path) { "%s/%s%s", furi_string_get_cstr(dev->folder), dev->dev_name, - NFC_APP_EXTENSION); + NFC_APP_FILENAME_EXTENSION); } if(!nfc_device_load_data(dev, path, true)) break; restored = true; diff --git a/lib/nfc/nfc_device.h b/lib/nfc/nfc_device.h index 20df4f891..76de0b61c 100644 --- a/lib/nfc/nfc_device.h +++ b/lib/nfc/nfc_device.h @@ -21,7 +21,8 @@ extern "C" { #define NFC_READER_DATA_MAX_SIZE 64 #define NFC_DICT_KEY_BATCH_SIZE 10 -#define NFC_APP_EXTENSION ".nfc" +#define NFC_APP_FILENAME_PREFIX "NFC" +#define NFC_APP_FILENAME_EXTENSION ".nfc" #define NFC_APP_SHADOW_EXTENSION ".shd" typedef void (*NfcLoadingCallback)(void* context, bool state); diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index c9d2b3017..4a8ae1d5e 100644 --- a/lib/subghz/protocols/raw.c +++ b/lib/subghz/protocols/raw.c @@ -108,7 +108,8 @@ bool subghz_protocol_raw_save_to_file_init( furi_string_set(instance->file_name, dev_name); // First remove subghz device file if it was saved - furi_string_printf(temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, dev_name, SUBGHZ_APP_EXTENSION); + furi_string_printf( + temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, dev_name, SUBGHZ_APP_FILENAME_EXTENSION); if(!storage_simply_remove(instance->storage, furi_string_get_cstr(temp_str))) { break; diff --git a/lib/subghz/types.h b/lib/subghz/types.h index cccf70bad..93f94cc74 100644 --- a/lib/subghz/types.h +++ b/lib/subghz/types.h @@ -13,7 +13,8 @@ #define SUBGHZ_APP_FOLDER ANY_PATH("subghz") #define SUBGHZ_RAW_FOLDER EXT_PATH("subghz") -#define SUBGHZ_APP_EXTENSION ".sub" +#define SUBGHZ_APP_FILENAME_PREFIX "SubGHz" +#define SUBGHZ_APP_FILENAME_EXTENSION ".sub" #define SUBGHZ_KEY_FILE_VERSION 1 #define SUBGHZ_KEY_FILE_TYPE "Flipper SubGhz Key File" diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index 761755d2d..04fd8567f 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -13,7 +13,7 @@ env.Append( File("manchester_decoder.h"), File("manchester_encoder.h"), File("path.h"), - File("random_name.h"), + File("name_generator.h"), File("sha256.h"), File("crc32_calc.h"), File("dir_walk.h"), diff --git a/lib/toolbox/name_generator.c b/lib/toolbox/name_generator.c new file mode 100644 index 000000000..36366485a --- /dev/null +++ b/lib/toolbox/name_generator.c @@ -0,0 +1,75 @@ +#include "name_generator.h" + +#include +#include +#include +#include +#include +#include + +const char* const name_generator_left[] = { + "ancient", "hollow", "strange", "disappeared", "unknown", "unthinkable", "unnameable", + "nameless", "my", "concealed", "forgotten", "hidden", "mysterious", "obscure", + "random", "remote", "uncharted", "undefined", "untraveled", "untold", +}; + +const char* const name_generator_right[] = { + "door", + "entrance", + "doorway", + "entry", + "portal", + "entree", + "opening", + "crack", + "access", + "corridor", + "passage", + "port", +}; + +void name_generator_make_auto(char* name, size_t max_name_size, const char* prefix) { + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDetailedFilename)) { + name_generator_make_detailed(name, max_name_size, prefix); + } else { + name_generator_make_random(name, max_name_size); + } +} + +void name_generator_make_random(char* name, size_t max_name_size) { + furi_assert(name); + furi_assert(max_name_size); + + uint8_t name_generator_left_i = rand() % COUNT_OF(name_generator_left); + uint8_t name_generator_right_i = rand() % COUNT_OF(name_generator_right); + + snprintf( + name, + max_name_size, + "%s_%s", + name_generator_left[name_generator_left_i], + name_generator_right[name_generator_right_i]); + + // Set first symbol to upper case + name[0] = name[0] - 0x20; +} + +void name_generator_make_detailed(char* name, size_t max_name_size, const char* prefix) { + furi_assert(name); + furi_assert(max_name_size); + furi_assert(prefix); + + FuriHalRtcDateTime dateTime; + furi_hal_rtc_get_datetime(&dateTime); + + snprintf( + name, + max_name_size, + "%s-%.4d_%.2d_%.2d-%.2d_%.2d", + prefix, + dateTime.year, + dateTime.month, + dateTime.day, + dateTime.hour, + dateTime.minute); +} diff --git a/lib/toolbox/name_generator.h b/lib/toolbox/name_generator.h new file mode 100644 index 000000000..bc17d54cd --- /dev/null +++ b/lib/toolbox/name_generator.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Generates detailed/random name based on furi_hal flags + * + * @param name buffer to write random name + * @param max_name_size length of given buffer + * @param[in] prefix The prefix of the name + */ +void name_generator_make_auto(char* name, size_t max_name_size, const char* prefix); + +/** Generates random name + * + * @param name buffer to write random name + * @param max_name_size length of given buffer + */ +void name_generator_make_random(char* name, size_t max_name_size); + +/** Generates detailed name + * + * @param name buffer to write random name + * @param max_name_size length of given buffer + * @param[in] prefix The prefix of the name + */ +void name_generator_make_detailed(char* name, size_t max_name_size, const char* prefix); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/toolbox/random_name.c b/lib/toolbox/random_name.c deleted file mode 100644 index 64e712c7c..000000000 --- a/lib/toolbox/random_name.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "random_name.h" -#include -#include -#include -#include - -void set_random_name(char* name, uint8_t max_name_size) { - const char* prefix[] = { - "ancient", "hollow", "strange", "disappeared", "unknown", - "unthinkable", "unnamable", "nameless", "my", "concealed", - "forgotten", "hidden", "mysterious", "obscure", "random", - "remote", "uncharted", "undefined", "untravelled", "untold", - }; - - const char* suffix[] = { - "door", - "entrance", - "doorway", - "entry", - "portal", - "entree", - "opening", - "crack", - "access", - "corridor", - "passage", - "port", - }; - uint8_t prefix_i = rand() % COUNT_OF(prefix); - uint8_t suffix_i = rand() % COUNT_OF(suffix); - - snprintf(name, max_name_size, "%s_%s", prefix[prefix_i], suffix[suffix_i]); - // Set first symbol to upper case - name[0] = name[0] - 0x20; -} diff --git a/lib/toolbox/random_name.h b/lib/toolbox/random_name.h deleted file mode 100644 index 358ea685d..000000000 --- a/lib/toolbox/random_name.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** Generates random name - * @param name buffer to write random name - * @param max_name_size length of given buffer - */ -void set_random_name(char* name, uint8_t max_name_size); - -#ifdef __cplusplus -} -#endif