mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-10 06:54:19 +00:00
Merge branch 'ofw-dev' into dev
This commit is contained in:
commit
15c480b68a
50 changed files with 538 additions and 322 deletions
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "../ibutton_i.h"
|
||||
|
||||
#include <toolbox/random_name.h>
|
||||
#include <toolbox/name_generator.h>
|
||||
#include <toolbox/path.h>
|
||||
|
||||
#include <dolphin/dolphin.h>
|
||||
|
@ -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);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "../infrared_i.h"
|
||||
|
||||
#include "common/infrared_scene_universal_common.h"
|
||||
#include <furi_hal_rtc.h>
|
||||
|
||||
void infrared_scene_universal_ac_on_enter(void* context) {
|
||||
infrared_scene_universal_common_on_enter(context);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include <lib/toolbox/random_name.h>
|
||||
#include "../lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
#include <toolbox/name_generator.h>
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "../nfc_i.h"
|
||||
#include <lib/toolbox/random_name.h>
|
||||
#include <lib/toolbox/name_generator.h>
|
||||
#include <gui/modules/validators.h>
|
||||
#include <toolbox/path.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
|
@ -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);
|
||||
|
|
|
@ -248,7 +248,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),
|
||||
|
|
|
@ -167,7 +167,6 @@ void subghz_scene_receiver_on_enter(void* context) {
|
|||
}
|
||||
furi_string_free(item_name);
|
||||
furi_string_free(item_time);
|
||||
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);
|
||||
|
@ -182,6 +181,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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#include "../subghz_i.h"
|
||||
#include "subghz/types.h"
|
||||
#include <lib/toolbox/random_name.h>
|
||||
#include "../helpers/subghz_custom_event.h"
|
||||
#include <lib/subghz/protocols/raw.h>
|
||||
#include <gui/modules/validators.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
#include <toolbox/name_generator.h>
|
||||
|
||||
#define MAX_TEXT_INPUT_LEN 23
|
||||
|
||||
|
@ -79,8 +79,8 @@ void subghz_scene_save_name_on_enter(void* context) {
|
|||
subghz_scene_save_name_get_timefilename(file_name, "S", true);
|
||||
}
|
||||
} else {
|
||||
set_random_name(file_name_buf, SUBGHZ_MAX_LEN_NAME);
|
||||
furi_string_set(file_name, file_name_buf);
|
||||
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
|
||||
|
@ -112,7 +112,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);
|
||||
|
@ -137,7 +137,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;
|
||||
|
|
|
@ -258,7 +258,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);
|
||||
|
||||
|
@ -267,7 +267,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;
|
||||
}
|
||||
|
@ -341,7 +341,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
|
||||
|
@ -415,7 +416,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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
#include <stdint.h>
|
||||
#include <u8g2_glue.h>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -2,13 +2,10 @@
|
|||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
|
||||
#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 +92,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 +166,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 +210,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;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
struct ViewPort {
|
||||
Gui* gui;
|
||||
FuriMutex* mutex;
|
||||
bool is_enabled;
|
||||
ViewPortOrientation orientation;
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include <stdio.h>
|
||||
#include <m-dict.h>
|
||||
|
||||
#include <bt/bt_service/bt.h>
|
||||
|
||||
#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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 7e011a95863716e72e7c6b5d552bca241d688304
|
||||
Subproject commit 327163d5867c7aa3051334c93ced718d15bfe4da
|
|
@ -72,6 +72,7 @@ FIRMWARE_APPS = {
|
|||
"unit_tests": [
|
||||
"basic_services",
|
||||
"updater_app",
|
||||
"radio_device_cc1101_ext",
|
||||
"unit_tests",
|
||||
],
|
||||
}
|
||||
|
|
|
@ -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,,
|
||||
|
@ -1704,6 +1704,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*
|
||||
|
@ -1924,7 +1927,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"
|
||||
|
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
const GpioPin* pin;
|
||||
const char* name;
|
||||
const uint8_t number;
|
||||
const bool debug;
|
||||
} GpioPinRecord;
|
||||
|
||||
|
|
|
@ -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,,
|
||||
|
@ -215,10 +215,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,,
|
||||
|
@ -2126,6 +2126,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*
|
||||
|
@ -2573,7 +2576,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"
|
||||
|
|
|
|
@ -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--;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
const GpioPin* pin;
|
||||
const char* name;
|
||||
const uint8_t number;
|
||||
const bool debug;
|
||||
} GpioPinRecord;
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ typedef enum {
|
|||
FuriHalRtcFlagHandOrient = (1 << 4),
|
||||
FuriHalRtcFlagLegacySleep = (1 << 5),
|
||||
FuriHalRtcFlagStealthMode = (1 << 6),
|
||||
FuriHalRtcFlagDetailedFilename = (1 << 7),
|
||||
} FuriHalRtcFlag;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -1366,7 +1366,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);
|
||||
}
|
||||
|
||||
|
@ -1593,7 +1593,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,
|
||||
|
@ -1665,7 +1665,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
|
||||
|
@ -1723,7 +1723,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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -382,7 +382,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;
|
||||
|
@ -394,13 +396,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 || SAK == 0x89)) {
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -14,7 +14,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"),
|
||||
|
|
91
lib/toolbox/name_generator.c
Normal file
91
lib/toolbox/name_generator.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include "name_generator.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <furi.h>
|
||||
|
||||
const char* const name_generator_left[] = {
|
||||
"super",
|
||||
"big",
|
||||
"little",
|
||||
"liquid",
|
||||
"unknown",
|
||||
"thin",
|
||||
"thick",
|
||||
"great",
|
||||
"my",
|
||||
"mini",
|
||||
"ultra",
|
||||
"haupt",
|
||||
"small",
|
||||
"random",
|
||||
"strange",
|
||||
};
|
||||
|
||||
const char* const name_generator_right[] = {
|
||||
"maslina",
|
||||
"sus",
|
||||
"anomalija",
|
||||
"artefact",
|
||||
"monolit",
|
||||
"burer",
|
||||
"sidorovich",
|
||||
"habar",
|
||||
"radar",
|
||||
"borov",
|
||||
"pda",
|
||||
"konserva",
|
||||
"aptechka",
|
||||
"door",
|
||||
"thing",
|
||||
"stuff",
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
35
lib/toolbox/name_generator.h
Normal file
35
lib/toolbox/name_generator.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#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
|
|
@ -1,51 +0,0 @@
|
|||
#include "random_name.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <furi.h>
|
||||
|
||||
void set_random_name(char* name, uint8_t max_name_size) {
|
||||
const char* prefix[] = {
|
||||
"super",
|
||||
"big",
|
||||
"little",
|
||||
"liquid",
|
||||
"unknown",
|
||||
"thin",
|
||||
"thick",
|
||||
"great",
|
||||
"my",
|
||||
"mini",
|
||||
"ultra",
|
||||
"haupt",
|
||||
"small",
|
||||
"random",
|
||||
"strange",
|
||||
};
|
||||
|
||||
const char* suffix[] = {
|
||||
"maslina",
|
||||
"sus",
|
||||
"anomalija",
|
||||
"artefact",
|
||||
"monolit",
|
||||
"burer",
|
||||
"sidorovich",
|
||||
"habar",
|
||||
"radar",
|
||||
"borov",
|
||||
"pda",
|
||||
"konserva",
|
||||
"aptechka",
|
||||
"door",
|
||||
"thing",
|
||||
"stuff",
|
||||
};
|
||||
// sus is not (sus)pect - this is about super sus
|
||||
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;
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
|
@ -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) &&
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue