From e9e76e144c13424869bf8afabfd8e8882baa0c24 Mon Sep 17 00:00:00 2001 From: Anna Prosvetova Date: Mon, 1 Nov 2021 23:35:54 +0300 Subject: [PATCH] RPC: Implement storage_stat_request (#800) * RPC: Update protobuf sources * RPC: Implement storage_stat_request * RPC: Test storage_stat_request * FuriRecord: fix use after free in destroy method. * Furi: refactor PubSub and it's usage. Fix allocation in RPC. * FuriCore: fix memory leak in pubsub * FuriCore: update unsubscribe method signature in pubsub, make subscription structure lighter. * FuriCore: remove dead code Co-authored-by: Aleksandr Kutuzov --- applications/bt/bt_service/bt.c | 4 +- applications/gui/gui.c | 2 +- applications/gui/gui_i.h | 2 +- applications/gui/icon_animation.c | 1 - applications/input/input.c | 14 +- applications/input/input.h | 2 +- applications/input/input_i.h | 4 +- applications/loader/loader.c | 4 +- applications/notification/notification-app.c | 2 +- applications/notification/notification-app.h | 2 +- applications/power/power_service/power.c | 22 +-- applications/power/power_service/power.h | 2 +- applications/power/power_service/power_api.c | 5 +- applications/power/power_service/power_i.h | 2 +- applications/rpc/rpc_gui.c | 8 +- applications/rpc/rpc_i.h | 3 + applications/rpc/rpc_storage.c | 42 +++++- applications/storage/storage-glue.h | 2 + applications/subghz/subghz_cli.c | 1 + applications/tests/furi_pubsub_test.c | 31 ++-- applications/tests/rpc/rpc_test.c | 76 +++++++++- applications/tests/test_index.c | 1 + assets/compiled/flipper.pb.h | 14 +- assets/compiled/storage.pb.c | 6 + assets/compiled/storage.pb.h | 32 ++++ assets/protobuf | 2 +- core/furi.h | 4 + core/furi/pubsub.c | 137 +++++++++--------- core/furi/pubsub.h | 119 ++++++--------- core/furi/record.c | 2 +- core/furi/stdglue.c | 3 + firmware/targets/f6/furi-hal/furi-hal-spi.c | 2 +- .../targets/f6/furi-hal/furi-hal-subghz.c | 2 +- firmware/targets/f7/furi-hal/furi-hal-spi.c | 2 +- .../targets/f7/furi-hal/furi-hal-subghz.c | 2 +- lib/common-api/task-control-block.h | 4 +- lib/irda/worker/irda_worker.c | 1 + 37 files changed, 350 insertions(+), 214 deletions(-) mode change 100755 => 100644 applications/loader/loader.c diff --git a/applications/bt/bt_service/bt.c b/applications/bt/bt_service/bt.c index 2ea1599b..de4c58d4 100755 --- a/applications/bt/bt_service/bt.c +++ b/applications/bt/bt_service/bt.c @@ -69,8 +69,8 @@ Bt* bt_alloc() { // Power bt->power = furi_record_open("power"); - PubSub* power_pubsub = power_get_pubsub(bt->power); - subscribe_pubsub(power_pubsub, bt_battery_level_changed_callback, bt); + FuriPubSub* power_pubsub = power_get_pubsub(bt->power); + furi_pubsub_subscribe(power_pubsub, bt_battery_level_changed_callback, bt); // RPC bt->rpc = furi_record_open("rpc"); diff --git a/applications/gui/gui.c b/applications/gui/gui.c index 95f58eb7..2976f909 100644 --- a/applications/gui/gui.c +++ b/applications/gui/gui.c @@ -410,7 +410,7 @@ Gui* gui_alloc() { gui->input_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL); gui->input_events = furi_record_open("input_events"); furi_check(gui->input_events); - subscribe_pubsub(gui->input_events, gui_input_events_callback, gui); + furi_pubsub_subscribe(gui->input_events, gui_input_events_callback, gui); // Cli gui->cli = furi_record_open("cli"); cli_add_command( diff --git a/applications/gui/gui_i.h b/applications/gui/gui_i.h index cfbf604f..5b32f602 100644 --- a/applications/gui/gui_i.h +++ b/applications/gui/gui_i.h @@ -50,7 +50,7 @@ struct Gui { // Input osMessageQueueId_t input_queue; - PubSub* input_events; + FuriPubSub* input_events; uint8_t ongoing_input; ViewPort* ongoing_input_view_port; diff --git a/applications/gui/icon_animation.c b/applications/gui/icon_animation.c index 22089d63..3ed0973d 100644 --- a/applications/gui/icon_animation.c +++ b/applications/gui/icon_animation.c @@ -2,7 +2,6 @@ #include "icon_i.h" #include -#include IconAnimation* icon_animation_alloc(const Icon* icon) { furi_assert(icon); diff --git a/applications/input/input.c b/applications/input/input.c index 62be3dba..1d160e55 100644 --- a/applications/input/input.c +++ b/applications/input/input.c @@ -28,11 +28,11 @@ void input_press_timer_callback(void* arg) { input_pin->press_counter++; if(input_pin->press_counter == INPUT_LONG_PRESS_COUNTS) { event.type = InputTypeLong; - notify_pubsub(&input->event_pubsub, &event); + furi_pubsub_publish(input->event_pubsub, &event); } else if(input_pin->press_counter > INPUT_LONG_PRESS_COUNTS) { input_pin->press_counter--; event.type = InputTypeRepeat; - notify_pubsub(&input->event_pubsub, &event); + furi_pubsub_publish(input->event_pubsub, &event); } } @@ -89,7 +89,7 @@ void input_cli_send(Cli* cli, string_t args, void* context) { return; } // Publish input event - notify_pubsub(&input->event_pubsub, &event); + furi_pubsub_publish(input->event_pubsub, &event); } const char* input_get_key_name(InputKey key) { @@ -120,8 +120,8 @@ const char* input_get_type_name(InputType type) { int32_t input_srv() { input = furi_alloc(sizeof(Input)); input->thread = osThreadGetId(); - init_pubsub(&input->event_pubsub); - furi_record_create("input_events", &input->event_pubsub); + input->event_pubsub = furi_pubsub_alloc(); + furi_record_create("input_events", input->event_pubsub); input->cli = furi_record_open("cli"); if(input->cli) { @@ -168,14 +168,14 @@ int32_t input_srv() { input_timer_stop(input->pin_states[i].press_timer); if(input->pin_states[i].press_counter < INPUT_LONG_PRESS_COUNTS) { event.type = InputTypeShort; - notify_pubsub(&input->event_pubsub, &event); + furi_pubsub_publish(input->event_pubsub, &event); } input->pin_states[i].press_counter = 0; } // Send Press/Release event event.type = input->pin_states[i].state ? InputTypePress : InputTypeRelease; - notify_pubsub(&input->event_pubsub, &event); + furi_pubsub_publish(input->event_pubsub, &event); } } diff --git a/applications/input/input.h b/applications/input/input.h index d848b1c6..08723795 100644 --- a/applications/input/input.h +++ b/applications/input/input.h @@ -18,7 +18,7 @@ typedef enum { InputTypeRepeat, /**< Repeat event, emmited with INPUT_REPEATE_PRESS period after InputTypeLong event */ } InputType; -/** Input Event, dispatches with PubSub */ +/** Input Event, dispatches with FuriPubSub */ typedef struct { uint32_t sequence; InputKey key; diff --git a/applications/input/input_i.h b/applications/input/input_i.h index db314dad..2111de7c 100644 --- a/applications/input/input_i.h +++ b/applications/input/input_i.h @@ -6,8 +6,6 @@ #pragma once #include "input.h" -#include -#include #include #include #include @@ -35,7 +33,7 @@ typedef struct { /** Input state */ typedef struct { osThreadId_t thread; - PubSub event_pubsub; + FuriPubSub* event_pubsub; InputPinState* pin_states; Cli* cli; volatile uint32_t counter; diff --git a/applications/loader/loader.c b/applications/loader/loader.c old mode 100755 new mode 100644 index d52eaa18..574db256 --- a/applications/loader/loader.c +++ b/applications/loader/loader.c @@ -140,7 +140,7 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con Loader* instance = context; if(thread_state == FuriThreadStateRunning) { - instance->free_heap_size = xPortGetFreeHeapSize(); + instance->free_heap_size = memmgr_get_free_heap(); } else if(thread_state == FuriThreadStateStopped) { /* * Current Leak Sanitizer assumes that memory is allocated and freed @@ -153,7 +153,7 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con * both values should be taken into account. */ delay(20); - int heap_diff = instance->free_heap_size - xPortGetFreeHeapSize(); + int heap_diff = instance->free_heap_size - memmgr_get_free_heap(); FURI_LOG_I( LOADER_LOG_TAG, "Application thread stopped. Heap allocation balance: %d. Thread allocation balance: %d.", diff --git a/applications/notification/notification-app.c b/applications/notification/notification-app.c index 22b6794e..3912cf62 100644 --- a/applications/notification/notification-app.c +++ b/applications/notification/notification-app.c @@ -427,7 +427,7 @@ static NotificationApp* notification_app_alloc() { // display backlight control app->event_record = furi_record_open("input_events"); - subscribe_pubsub(app->event_record, input_event_callback, app); + furi_pubsub_subscribe(app->event_record, input_event_callback, app); notification_message(app, &sequence_display_on); return app; diff --git a/applications/notification/notification-app.h b/applications/notification/notification-app.h index 78c58f6d..f1fe5cef 100644 --- a/applications/notification/notification-app.h +++ b/applications/notification/notification-app.h @@ -44,7 +44,7 @@ typedef struct { struct NotificationApp { osMessageQueueId_t queue; - PubSub* event_record; + FuriPubSub* event_record; osTimerId_t display_timer; NotificationLedLayer display; diff --git a/applications/power/power_service/power.c b/applications/power/power_service/power.c index de712fd4..94137d73 100755 --- a/applications/power/power_service/power.c +++ b/applications/power/power_service/power.c @@ -31,7 +31,7 @@ Power* power_alloc() { power->gui = furi_record_open("gui"); // Pubsub - init_pubsub(&power->event_pubsub); + power->event_pubsub = furi_pubsub_alloc(); // State initialization power->state = PowerStateNotCharging; @@ -60,10 +60,6 @@ Power* power_alloc() { void power_free(Power* power) { furi_assert(power); - // Records - furi_record_close("notification"); - furi_record_close("gui"); - // Gui view_dispatcher_remove_view(power->view_dispatcher, PowerViewOff); power_off_free(power->power_off); @@ -73,6 +69,14 @@ void power_free(Power* power) { // State osMutexDelete(power->info_mtx); + + // FuriPubSub + furi_pubsub_free(power->event_pubsub); + + // Records + furi_record_close("notification"); + furi_record_close("gui"); + free(power); } @@ -83,14 +87,14 @@ static void power_check_charging_state(Power* power) { notification_internal_message(power->notification, &sequence_charged); power->state = PowerStateCharged; power->event.type = PowerEventTypeFullyCharged; - notify_pubsub(&power->event_pubsub, &power->event); + furi_pubsub_publish(power->event_pubsub, &power->event); } } else { if(power->state != PowerStateCharging) { notification_internal_message(power->notification, &sequence_charging); power->state = PowerStateCharging; power->event.type = PowerEventTypeStartCharging; - notify_pubsub(&power->event_pubsub, &power->event); + furi_pubsub_publish(power->event_pubsub, &power->event); } } } else { @@ -98,7 +102,7 @@ static void power_check_charging_state(Power* power) { notification_internal_message(power->notification, &sequence_not_charging); power->state = PowerStateNotCharging; power->event.type = PowerEventTypeStopCharging; - notify_pubsub(&power->event_pubsub, &power->event); + furi_pubsub_publish(power->event_pubsub, &power->event); } } } @@ -156,7 +160,7 @@ static void power_check_battery_level_change(Power* power) { power->battery_level = power->info.charge; power->event.type = PowerEventTypeBatteryLevelChanged; power->event.data.battery_level = power->battery_level; - notify_pubsub(&power->event_pubsub, &power->event); + furi_pubsub_publish(power->event_pubsub, &power->event); } } diff --git a/applications/power/power_service/power.h b/applications/power/power_service/power.h index d3dec410..947d917c 100644 --- a/applications/power/power_service/power.h +++ b/applications/power/power_service/power.h @@ -62,4 +62,4 @@ void power_get_info(Power* power, PowerInfo* info); /** Get power event pubsub handler * @param power - Power instance */ -PubSub* power_get_pubsub(Power* power); +FuriPubSub* power_get_pubsub(Power* power); diff --git a/applications/power/power_service/power_api.c b/applications/power/power_service/power_api.c index 46fa21ef..a3278f9b 100644 --- a/applications/power/power_service/power_api.c +++ b/applications/power/power_service/power_api.c @@ -1,4 +1,5 @@ #include "power_i.h" + #include #include "furi-hal-power.h" #include "furi-hal-bootloader.h" @@ -30,7 +31,7 @@ void power_get_info(Power* power, PowerInfo* info) { osMutexRelease(power->info_mtx); } -PubSub* power_get_pubsub(Power* power) { +FuriPubSub* power_get_pubsub(Power* power) { furi_assert(power); - return &power->event_pubsub; + return power->event_pubsub; } diff --git a/applications/power/power_service/power_i.h b/applications/power/power_service/power_i.h index 5bebd8cb..9833df5f 100755 --- a/applications/power/power_service/power_i.h +++ b/applications/power/power_service/power_i.h @@ -25,7 +25,7 @@ struct Power { ViewPort* battery_view_port; Gui* gui; NotificationApp* notification; - PubSub event_pubsub; + FuriPubSub* event_pubsub; PowerEvent event; PowerState state; diff --git a/applications/rpc/rpc_gui.c b/applications/rpc/rpc_gui.c index e5a6aeb9..10a0afd9 100644 --- a/applications/rpc/rpc_gui.c +++ b/applications/rpc/rpc_gui.c @@ -113,9 +113,9 @@ void rpc_system_gui_send_input_event_request_process(const PB_Main* request, voi return; } - PubSub* input_events = furi_record_open("input_events"); + FuriPubSub* input_events = furi_record_open("input_events"); furi_check(input_events); - notify_pubsub(input_events, &event); + furi_pubsub_publish(input_events, &event); furi_record_close("input_events"); rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK); } @@ -142,11 +142,13 @@ void* rpc_system_gui_alloc(Rpc* rpc) { rpc_handler.message_handler = rpc_system_gui_send_input_event_request_process; rpc_add_handler(rpc, PB_Main_gui_send_input_event_request_tag, &rpc_handler); - return NULL; + return rpc_gui; } void rpc_system_gui_free(void* ctx) { + furi_assert(ctx); RpcGuiSystem* rpc_gui = ctx; + furi_assert(rpc_gui->gui); gui_set_framebuffer_callback(rpc_gui->gui, NULL, NULL); furi_record_close("gui"); free(rpc_gui); diff --git a/applications/rpc/rpc_i.h b/applications/rpc/rpc_i.h index fdfcfde9..76df1e5a 100644 --- a/applications/rpc/rpc_i.h +++ b/applications/rpc/rpc_i.h @@ -1,5 +1,6 @@ #pragma once #include "rpc.h" +#include "storage/filesystem-api-defines.h" #include #include #include @@ -29,3 +30,5 @@ void rpc_system_gui_free(void* ctx); void rpc_print_message(const PB_Main* message); void rpc_cli_command_start_session(Cli* cli, string_t args, void* context); + +PB_CommandStatus rpc_system_storage_get_error(FS_Error fs_error); \ No newline at end of file diff --git a/applications/rpc/rpc_storage.c b/applications/rpc/rpc_storage.c index f8e0a97e..99844e5d 100644 --- a/applications/rpc/rpc_storage.c +++ b/applications/rpc/rpc_storage.c @@ -51,7 +51,7 @@ static void rpc_system_storage_reset_state(RpcStorageSystem* rpc_storage, bool s } } -static PB_CommandStatus rpc_system_storage_get_error(FS_Error fs_error) { +PB_CommandStatus rpc_system_storage_get_error(FS_Error fs_error) { PB_CommandStatus pb_error; switch(fs_error) { case FSE_OK: @@ -96,6 +96,40 @@ static PB_CommandStatus rpc_system_storage_get_file_error(File* file) { return rpc_system_storage_get_error(storage_file_get_error(file)); } +static void rpc_system_storage_stat_process(const PB_Main* request, void* context) { + furi_assert(request); + furi_assert(context); + furi_assert(request->which_content == PB_Main_storage_stat_request_tag); + + RpcStorageSystem* rpc_storage = context; + rpc_system_storage_reset_state(rpc_storage, true); + + PB_Main* response = furi_alloc(sizeof(PB_Main)); + response->command_id = request->command_id; + + Storage* fs_api = furi_record_open("storage"); + + const char* path = request->content.storage_stat_request.path; + FileInfo fileinfo; + FS_Error error = storage_common_stat(fs_api, path, &fileinfo); + + response->command_status = rpc_system_storage_get_error(error); + response->which_content = PB_Main_empty_tag; + + if(error == FSE_OK) { + response->which_content = PB_Main_storage_stat_response_tag; + response->content.storage_stat_response.has_file = true; + response->content.storage_stat_response.file.type = (fileinfo.flags & FSF_DIRECTORY) ? + PB_Storage_File_FileType_DIR : + PB_Storage_File_FileType_FILE; + response->content.storage_stat_response.file.size = fileinfo.size; + } + + rpc_send_and_release(rpc_storage->rpc, response); + free(response); + furi_record_close("storage"); +} + static void rpc_system_storage_list_root(const PB_Main* request, void* context) { RpcStorageSystem* rpc_storage = context; const char* hard_coded_dirs[] = {"any", "int", "ext"}; @@ -140,11 +174,10 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex PB_Main response = { .command_id = request->command_id, .has_next = false, - .which_content = PB_Main_storage_list_request_tag, + .which_content = PB_Main_storage_list_response_tag, .command_status = PB_CommandStatus_OK, }; PB_Storage_ListResponse* list = &response.content.storage_list_response; - response.which_content = PB_Main_storage_list_response_tag; bool finish = false; int i = 0; @@ -434,6 +467,9 @@ void* rpc_system_storage_alloc(Rpc* rpc) { .context = rpc_storage, }; + rpc_handler.message_handler = rpc_system_storage_stat_process; + rpc_add_handler(rpc, PB_Main_storage_stat_request_tag, &rpc_handler); + rpc_handler.message_handler = rpc_system_storage_list_process; rpc_add_handler(rpc, PB_Main_storage_list_request_tag, &rpc_handler); diff --git a/applications/storage/storage-glue.h b/applications/storage/storage-glue.h index 775742cc..3a6cbe5c 100644 --- a/applications/storage/storage-glue.h +++ b/applications/storage/storage-glue.h @@ -1,8 +1,10 @@ #pragma once + #include #include "filesystem-api-internal.h" #include #include +#include #ifdef __cplusplus extern "C" { diff --git a/applications/subghz/subghz_cli.c b/applications/subghz/subghz_cli.c index 4a2f06c0..4c1abcf8 100644 --- a/applications/subghz/subghz_cli.c +++ b/applications/subghz/subghz_cli.c @@ -3,6 +3,7 @@ #include #include #include + #include #include #include diff --git a/applications/tests/furi_pubsub_test.c b/applications/tests/furi_pubsub_test.c index d52b6bd3..010a00ab 100644 --- a/applications/tests/furi_pubsub_test.c +++ b/applications/tests/furi_pubsub_test.c @@ -16,39 +16,30 @@ void test_pubsub_handler(const void* arg, void* ctx) { } void test_furi_pubsub() { - bool result; - PubSub test_pubsub; - PubSubItem* test_pubsub_item; + FuriPubSub* test_pubsub = NULL; + FuriPubSubSubscription* test_pubsub_subscription = NULL; // init pubsub case - result = init_pubsub(&test_pubsub); - mu_assert(result, "init pubsub failed"); + test_pubsub = furi_pubsub_alloc(); + mu_assert_pointers_not_eq(test_pubsub, NULL); // subscribe pubsub case - test_pubsub_item = subscribe_pubsub(&test_pubsub, test_pubsub_handler, (void*)&context_value); - mu_assert_pointers_not_eq(test_pubsub_item, NULL); + test_pubsub_subscription = + furi_pubsub_subscribe(test_pubsub, test_pubsub_handler, (void*)&context_value); + mu_assert_pointers_not_eq(test_pubsub_subscription, NULL); /// notify pubsub case - result = notify_pubsub(&test_pubsub, (void*)¬ify_value_0); - mu_assert(result, "notify pubsub failed"); + furi_pubsub_publish(test_pubsub, (void*)¬ify_value_0); mu_assert_int_eq(pubsub_value, notify_value_0); mu_assert_int_eq(pubsub_context_value, context_value); // unsubscribe pubsub case - result = unsubscribe_pubsub(test_pubsub_item); - mu_assert(result, "unsubscribe pubsub failed"); - - result = unsubscribe_pubsub(test_pubsub_item); - mu_assert(!result, "unsubscribe pubsub not failed"); + furi_pubsub_unsubscribe(test_pubsub, test_pubsub_subscription); /// notify unsubscribed pubsub case - result = notify_pubsub(&test_pubsub, (void*)¬ify_value_1); - mu_assert(result, "notify pubsub failed"); + furi_pubsub_publish(test_pubsub, (void*)¬ify_value_1); mu_assert_int_not_eq(pubsub_value, notify_value_1); // delete pubsub case - result = delete_pubsub(&test_pubsub); - mu_assert(result, "unsubscribe pubsub failed"); - - // TODO test case that the pubsub_delete will remove pubsub from heap + furi_pubsub_free(test_pubsub); } \ No newline at end of file diff --git a/applications/tests/rpc/rpc_test.c b/applications/tests/rpc/rpc_test.c index 26e4eccc..51ed30cf 100644 --- a/applications/tests/rpc/rpc_test.c +++ b/applications/tests/rpc/rpc_test.c @@ -218,6 +218,9 @@ static void test_rpc_create_simple_message( message->which_content = tag; message->has_next = false; switch(tag) { + 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; break; @@ -369,6 +372,19 @@ static void test_rpc_compare_messages(PB_Main* result, PB_Main* expected) { mu_check(result_locked == expected_locked); break; } + case PB_Main_storage_stat_response_tag: { + bool result_has_msg_file = result->content.storage_stat_response.has_file; + bool expected_has_msg_file = expected->content.storage_stat_response.has_file; + mu_check(result_has_msg_file == expected_has_msg_file); + + if(result_has_msg_file) { + PB_Storage_File* result_msg_file = &result->content.storage_stat_response.file; + PB_Storage_File* expected_msg_file = &expected->content.storage_stat_response.file; + test_rpc_compare_file(result_msg_file, expected_msg_file); + } else { + mu_check(0); + } + } break; case PB_Main_storage_read_response_tag: { bool result_has_msg_file = result->content.storage_read_response.has_file; bool expected_has_msg_file = expected->content.storage_read_response.has_file; @@ -455,11 +471,10 @@ static void test_rpc_storage_list_create_expected_list( PB_Main response = { .command_id = command_id, .has_next = false, - .which_content = PB_Main_storage_list_request_tag, + .which_content = PB_Main_storage_list_response_tag, /* other fields (e.g. msg_files ptrs) explicitly initialized by 0 */ }; PB_Storage_ListResponse* list = &response.content.storage_list_response; - response.which_content = PB_Main_storage_list_response_tag; bool finish = false; int i = 0; @@ -649,9 +664,8 @@ static bool test_is_exists(const char* path) { Storage* fs_api = furi_record_open("storage"); FileInfo fileinfo; FS_Error result = storage_common_stat(fs_api, path, &fileinfo); - furi_check((result == FSE_OK) || (result == FSE_NOT_EXIST)); - + furi_record_close("storage"); return result == FSE_OK; } @@ -687,6 +701,59 @@ static void test_create_file(const char* path, size_t size) { furi_check(test_is_exists(path)); } +static void test_rpc_storage_stat_run(const char* path, uint32_t command_id) { + PB_Main request; + 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); + + Storage* fs_api = furi_record_open("storage"); + FileInfo fileinfo; + FS_Error error = storage_common_stat(fs_api, path, &fileinfo); + furi_record_close("storage"); + + PB_Main* response = MsgList_push_new(expected_msg_list); + response->command_id = command_id; + response->command_status = rpc_system_storage_get_error(error); + response->has_next = false; + response->which_content = PB_Main_empty_tag; + + if(error == FSE_OK) { + response->which_content = PB_Main_storage_stat_response_tag; + response->content.storage_stat_response.has_file = true; + response->content.storage_stat_response.file.type = (fileinfo.flags & FSF_DIRECTORY) ? + PB_Storage_File_FileType_DIR : + PB_Storage_File_FileType_FILE; + response->content.storage_stat_response.file.size = fileinfo.size; + } + + test_rpc_encode_and_feed_one(&request); + test_rpc_decode_and_compare(expected_msg_list); + + pb_release(&PB_Main_msg, &request); + test_rpc_free_msg_list(expected_msg_list); +} + +#define TEST_DIR_STAT_NAME TEST_DIR "stat_dir" +#define TEST_DIR_STAT TEST_DIR_STAT_NAME "/" +MU_TEST(test_storage_stat) { + test_create_dir(TEST_DIR_STAT_NAME); + test_create_file(TEST_DIR_STAT "empty.txt", 0); + test_create_file(TEST_DIR_STAT "l33t.txt", 1337); + + test_rpc_storage_stat_run("/", ++command_id); + test_rpc_storage_stat_run("/int", ++command_id); + test_rpc_storage_stat_run("/ext", ++command_id); + + test_rpc_storage_stat_run(TEST_DIR_STAT "empty.txt", ++command_id); + test_rpc_storage_stat_run(TEST_DIR_STAT "l33t.txt", ++command_id); + test_rpc_storage_stat_run(TEST_DIR_STAT "missing", ++command_id); + test_rpc_storage_stat_run(TEST_DIR_STAT_NAME, ++command_id); + + test_rpc_storage_stat_run(TEST_DIR_STAT, ++command_id); +} + MU_TEST(test_storage_read) { test_create_file(TEST_DIR "empty.txt", 0); test_create_file(TEST_DIR "file1.txt", 1); @@ -1138,6 +1205,7 @@ MU_TEST_SUITE(test_rpc_status) { MU_TEST_SUITE(test_rpc_storage) { MU_SUITE_CONFIGURE(&test_rpc_storage_setup, &test_rpc_storage_teardown); + MU_RUN_TEST(test_storage_stat); MU_RUN_TEST(test_storage_list); MU_RUN_TEST(test_storage_read); MU_RUN_TEST(test_storage_write_read); diff --git a/applications/tests/test_index.c b/applications/tests/test_index.c index d55a1e45..d86e587a 100644 --- a/applications/tests/test_index.c +++ b/applications/tests/test_index.c @@ -1,4 +1,5 @@ #include "m-string.h" + #include #include #include diff --git a/assets/compiled/flipper.pb.h b/assets/compiled/flipper.pb.h index e1ff5491..161b969d 100644 --- a/assets/compiled/flipper.pb.h +++ b/assets/compiled/flipper.pb.h @@ -78,6 +78,8 @@ typedef struct _PB_Main { PB_Gui_StopScreenStreamRequest gui_stop_screen_stream_request; PB_Gui_ScreenStreamFrame gui_screen_stream_frame; PB_Gui_SendInputEventRequest gui_send_input_event_request; + PB_Storage_StatRequest storage_stat_request; + PB_Storage_StatResponse storage_stat_response; } content; } PB_Main; @@ -124,6 +126,8 @@ extern "C" { #define PB_Main_gui_stop_screen_stream_request_tag 21 #define PB_Main_gui_screen_stream_frame_tag 22 #define PB_Main_gui_send_input_event_request_tag 23 +#define PB_Main_storage_stat_request_tag 24 +#define PB_Main_storage_stat_response_tag 25 /* Struct field encoding specification for nanopb */ #define PB_Empty_FIELDLIST(X, a) \ @@ -159,7 +163,9 @@ X(a, STATIC, ONEOF, MSG_W_CB, (content,stop_session,content.stop_session), X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_start_screen_stream_request,content.gui_start_screen_stream_request), 20) \ X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_stop_screen_stream_request,content.gui_stop_screen_stream_request), 21) \ X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_screen_stream_frame,content.gui_screen_stream_frame), 22) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_send_input_event_request,content.gui_send_input_event_request), 23) +X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_send_input_event_request,content.gui_send_input_event_request), 23) \ +X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_stat_request,content.storage_stat_request), 24) \ +X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_stat_response,content.storage_stat_response), 25) #define PB_Main_CALLBACK NULL #define PB_Main_DEFAULT NULL #define PB_Main_content_empty_MSGTYPE PB_Empty @@ -182,6 +188,8 @@ X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_send_input_event_request,content #define PB_Main_content_gui_stop_screen_stream_request_MSGTYPE PB_Gui_StopScreenStreamRequest #define PB_Main_content_gui_screen_stream_frame_MSGTYPE PB_Gui_ScreenStreamFrame #define PB_Main_content_gui_send_input_event_request_MSGTYPE PB_Gui_SendInputEventRequest +#define PB_Main_content_storage_stat_request_MSGTYPE PB_Storage_StatRequest +#define PB_Main_content_storage_stat_response_MSGTYPE PB_Storage_StatResponse extern const pb_msgdesc_t PB_Empty_msg; extern const pb_msgdesc_t PB_StopSession_msg; @@ -195,9 +203,9 @@ extern const pb_msgdesc_t PB_Main_msg; /* Maximum encoded size of messages (where known) */ #define PB_Empty_size 0 #define PB_StopSession_size 0 -#if defined(PB_Storage_ListRequest_size) && defined(PB_Storage_ListResponse_size) && defined(PB_Storage_ReadRequest_size) && defined(PB_Storage_ReadResponse_size) && defined(PB_Storage_WriteRequest_size) && defined(PB_Storage_DeleteRequest_size) && defined(PB_Storage_MkdirRequest_size) && defined(PB_Storage_Md5sumRequest_size) && defined(PB_App_StartRequest_size) && defined(PB_Gui_ScreenStreamFrame_size) +#if defined(PB_Storage_ListRequest_size) && defined(PB_Storage_ListResponse_size) && defined(PB_Storage_ReadRequest_size) && defined(PB_Storage_ReadResponse_size) && defined(PB_Storage_WriteRequest_size) && defined(PB_Storage_DeleteRequest_size) && defined(PB_Storage_MkdirRequest_size) && defined(PB_Storage_Md5sumRequest_size) && defined(PB_App_StartRequest_size) && defined(PB_Gui_ScreenStreamFrame_size) && defined(PB_Storage_StatRequest_size) && defined(PB_Storage_StatResponse_size) #define PB_Main_size (10 + sizeof(union PB_Main_content_size_union)) -union PB_Main_content_size_union {char f7[(6 + PB_Storage_ListRequest_size)]; char f8[(6 + PB_Storage_ListResponse_size)]; char f9[(6 + PB_Storage_ReadRequest_size)]; char f10[(6 + PB_Storage_ReadResponse_size)]; char f11[(6 + PB_Storage_WriteRequest_size)]; char f12[(6 + PB_Storage_DeleteRequest_size)]; char f13[(6 + PB_Storage_MkdirRequest_size)]; char f14[(6 + PB_Storage_Md5sumRequest_size)]; char f16[(7 + PB_App_StartRequest_size)]; char f22[(7 + PB_Gui_ScreenStreamFrame_size)]; char f0[36];}; +union PB_Main_content_size_union {char f7[(6 + PB_Storage_ListRequest_size)]; char f8[(6 + PB_Storage_ListResponse_size)]; char f9[(6 + PB_Storage_ReadRequest_size)]; char f10[(6 + PB_Storage_ReadResponse_size)]; char f11[(6 + PB_Storage_WriteRequest_size)]; char f12[(6 + PB_Storage_DeleteRequest_size)]; char f13[(6 + PB_Storage_MkdirRequest_size)]; char f14[(6 + PB_Storage_Md5sumRequest_size)]; char f16[(7 + PB_App_StartRequest_size)]; char f22[(7 + PB_Gui_ScreenStreamFrame_size)]; char f24[(7 + PB_Storage_StatRequest_size)]; char f25[(7 + PB_Storage_StatResponse_size)]; char f0[36];}; #endif #ifdef __cplusplus diff --git a/assets/compiled/storage.pb.c b/assets/compiled/storage.pb.c index a74477e1..24577c23 100644 --- a/assets/compiled/storage.pb.c +++ b/assets/compiled/storage.pb.c @@ -9,6 +9,12 @@ PB_BIND(PB_Storage_File, PB_Storage_File, AUTO) +PB_BIND(PB_Storage_StatRequest, PB_Storage_StatRequest, AUTO) + + +PB_BIND(PB_Storage_StatResponse, PB_Storage_StatResponse, AUTO) + + PB_BIND(PB_Storage_ListRequest, PB_Storage_ListRequest, AUTO) diff --git a/assets/compiled/storage.pb.h b/assets/compiled/storage.pb.h index ea6291b9..2e82a8de 100644 --- a/assets/compiled/storage.pb.h +++ b/assets/compiled/storage.pb.h @@ -32,6 +32,10 @@ typedef struct _PB_Storage_ReadRequest { char *path; } PB_Storage_ReadRequest; +typedef struct _PB_Storage_StatRequest { + char *path; +} PB_Storage_StatRequest; + typedef struct _PB_Storage_DeleteRequest { char *path; bool recursive; @@ -58,6 +62,11 @@ typedef struct _PB_Storage_ReadResponse { PB_Storage_File file; } PB_Storage_ReadResponse; +typedef struct _PB_Storage_StatResponse { + bool has_file; + PB_Storage_File file; +} PB_Storage_StatResponse; + typedef struct _PB_Storage_WriteRequest { char *path; bool has_file; @@ -77,6 +86,8 @@ extern "C" { /* Initializer values for message structs */ #define PB_Storage_File_init_default {_PB_Storage_File_FileType_MIN, NULL, 0, NULL} +#define PB_Storage_StatRequest_init_default {NULL} +#define PB_Storage_StatResponse_init_default {false, PB_Storage_File_init_default} #define PB_Storage_ListRequest_init_default {NULL} #define PB_Storage_ListResponse_init_default {0, {PB_Storage_File_init_default, PB_Storage_File_init_default, PB_Storage_File_init_default, PB_Storage_File_init_default, PB_Storage_File_init_default, PB_Storage_File_init_default, PB_Storage_File_init_default, PB_Storage_File_init_default}} #define PB_Storage_ReadRequest_init_default {NULL} @@ -87,6 +98,8 @@ extern "C" { #define PB_Storage_Md5sumRequest_init_default {NULL} #define PB_Storage_Md5sumResponse_init_default {""} #define PB_Storage_File_init_zero {_PB_Storage_File_FileType_MIN, NULL, 0, NULL} +#define PB_Storage_StatRequest_init_zero {NULL} +#define PB_Storage_StatResponse_init_zero {false, PB_Storage_File_init_zero} #define PB_Storage_ListRequest_init_zero {NULL} #define PB_Storage_ListResponse_init_zero {0, {PB_Storage_File_init_zero, PB_Storage_File_init_zero, PB_Storage_File_init_zero, PB_Storage_File_init_zero, PB_Storage_File_init_zero, PB_Storage_File_init_zero, PB_Storage_File_init_zero, PB_Storage_File_init_zero}} #define PB_Storage_ReadRequest_init_zero {NULL} @@ -102,6 +115,7 @@ extern "C" { #define PB_Storage_Md5sumRequest_path_tag 1 #define PB_Storage_MkdirRequest_path_tag 1 #define PB_Storage_ReadRequest_path_tag 1 +#define PB_Storage_StatRequest_path_tag 1 #define PB_Storage_DeleteRequest_path_tag 1 #define PB_Storage_DeleteRequest_recursive_tag 2 #define PB_Storage_File_type_tag 1 @@ -111,6 +125,7 @@ extern "C" { #define PB_Storage_Md5sumResponse_md5sum_tag 1 #define PB_Storage_ListResponse_file_tag 1 #define PB_Storage_ReadResponse_file_tag 1 +#define PB_Storage_StatResponse_file_tag 1 #define PB_Storage_WriteRequest_path_tag 1 #define PB_Storage_WriteRequest_file_tag 2 @@ -123,6 +138,17 @@ X(a, POINTER, SINGULAR, BYTES, data, 4) #define PB_Storage_File_CALLBACK NULL #define PB_Storage_File_DEFAULT NULL +#define PB_Storage_StatRequest_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, path, 1) +#define PB_Storage_StatRequest_CALLBACK NULL +#define PB_Storage_StatRequest_DEFAULT NULL + +#define PB_Storage_StatResponse_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, file, 1) +#define PB_Storage_StatResponse_CALLBACK NULL +#define PB_Storage_StatResponse_DEFAULT NULL +#define PB_Storage_StatResponse_file_MSGTYPE PB_Storage_File + #define PB_Storage_ListRequest_FIELDLIST(X, a) \ X(a, POINTER, SINGULAR, STRING, path, 1) #define PB_Storage_ListRequest_CALLBACK NULL @@ -174,6 +200,8 @@ X(a, STATIC, SINGULAR, STRING, md5sum, 1) #define PB_Storage_Md5sumResponse_DEFAULT NULL extern const pb_msgdesc_t PB_Storage_File_msg; +extern const pb_msgdesc_t PB_Storage_StatRequest_msg; +extern const pb_msgdesc_t PB_Storage_StatResponse_msg; extern const pb_msgdesc_t PB_Storage_ListRequest_msg; extern const pb_msgdesc_t PB_Storage_ListResponse_msg; extern const pb_msgdesc_t PB_Storage_ReadRequest_msg; @@ -186,6 +214,8 @@ extern const pb_msgdesc_t PB_Storage_Md5sumResponse_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define PB_Storage_File_fields &PB_Storage_File_msg +#define PB_Storage_StatRequest_fields &PB_Storage_StatRequest_msg +#define PB_Storage_StatResponse_fields &PB_Storage_StatResponse_msg #define PB_Storage_ListRequest_fields &PB_Storage_ListRequest_msg #define PB_Storage_ListResponse_fields &PB_Storage_ListResponse_msg #define PB_Storage_ReadRequest_fields &PB_Storage_ReadRequest_msg @@ -198,6 +228,8 @@ extern const pb_msgdesc_t PB_Storage_Md5sumResponse_msg; /* Maximum encoded size of messages (where known) */ /* PB_Storage_File_size depends on runtime parameters */ +/* PB_Storage_StatRequest_size depends on runtime parameters */ +/* PB_Storage_StatResponse_size depends on runtime parameters */ /* PB_Storage_ListRequest_size depends on runtime parameters */ /* PB_Storage_ListResponse_size depends on runtime parameters */ /* PB_Storage_ReadRequest_size depends on runtime parameters */ diff --git a/assets/protobuf b/assets/protobuf index 76f43b8c..0e6d374a 160000 --- a/assets/protobuf +++ b/assets/protobuf @@ -1 +1 @@ -Subproject commit 76f43b8c6510306d40c006b696d9d1b14a252dc1 +Subproject commit 0e6d374ab1a12f95a3cd04444376a261e7252db4 diff --git a/core/furi.h b/core/furi.h index 681855d0..80aea70c 100644 --- a/core/furi.h +++ b/core/furi.h @@ -1,5 +1,9 @@ #pragma once +#include +#include +#include + #include #include diff --git a/core/furi/pubsub.c b/core/furi/pubsub.c index 0722d2a0..3fbcb51c 100644 --- a/core/furi/pubsub.c +++ b/core/furi/pubsub.c @@ -1,88 +1,95 @@ #include "pubsub.h" -#include +#include "memmgr.h" +#include "check.h" + +#include +#include + +struct FuriPubSubSubscription { + FuriPubSubCallback callback; + void* callback_context; +}; + +LIST_DEF(FuriPubSubSubscriptionList, FuriPubSubSubscription, M_POD_OPLIST); + +struct FuriPubSub { + FuriPubSubSubscriptionList_t items; + osMutexId_t mutex; +}; + +FuriPubSub* furi_pubsub_alloc() { + FuriPubSub* pubsub = furi_alloc(sizeof(FuriPubSub)); -bool init_pubsub(PubSub* pubsub) { - // mutex without name, - // no attributes (unfortunatly robust mutex is not supported by FreeRTOS), - // with dynamic memory allocation pubsub->mutex = osMutexNew(NULL); - if(pubsub->mutex == NULL) return false; + furi_assert(pubsub->mutex); - // construct list - list_pubsub_cb_init(pubsub->items); + FuriPubSubSubscriptionList_init(pubsub->items); - return true; + return pubsub; } -bool delete_pubsub(PubSub* pubsub) { - if(osMutexAcquire(pubsub->mutex, osWaitForever) == osOK) { - bool result = osMutexDelete(pubsub->mutex) == osOK; - list_pubsub_cb_clear(pubsub->items); - return result; - } else { - return false; - } +void furi_pubsub_free(FuriPubSub* pubsub) { + furi_assert(pubsub); + + furi_check(FuriPubSubSubscriptionList_size(pubsub->items) == 0); + + FuriPubSubSubscriptionList_clear(pubsub->items); + + furi_check(osMutexDelete(pubsub->mutex) == osOK); + + free(pubsub); } -PubSubItem* subscribe_pubsub(PubSub* pubsub, PubSubCallback cb, void* ctx) { - if(osMutexAcquire(pubsub->mutex, osWaitForever) == osOK) { - // put uninitialized item to the list - PubSubItem* item = list_pubsub_cb_push_raw(pubsub->items); +FuriPubSubSubscription* + furi_pubsub_subscribe(FuriPubSub* pubsub, FuriPubSubCallback callback, void* callback_context) { + furi_check(osMutexAcquire(pubsub->mutex, osWaitForever) == osOK); + // put uninitialized item to the list + FuriPubSubSubscription* item = FuriPubSubSubscriptionList_push_raw(pubsub->items); - // initialize item - item->cb = cb; - item->ctx = ctx; - item->self = pubsub; + // initialize item + item->callback = callback; + item->callback_context = callback_context; - // TODO unsubscribe pubsub on app exit - //flapp_on_exit(unsubscribe_pubsub, item); + furi_check(osMutexRelease(pubsub->mutex) == osOK); - osMutexRelease(pubsub->mutex); - - return item; - } else { - return NULL; - } + return item; } -bool unsubscribe_pubsub(PubSubItem* pubsub_id) { - if(osMutexAcquire(pubsub_id->self->mutex, osWaitForever) == osOK) { - bool result = false; +void furi_pubsub_unsubscribe(FuriPubSub* pubsub, FuriPubSubSubscription* pubsub_subscription) { + furi_assert(pubsub); + furi_assert(pubsub_subscription); - // iterate over items - list_pubsub_cb_it_t it; - for(list_pubsub_cb_it(it, pubsub_id->self->items); !list_pubsub_cb_end_p(it); - list_pubsub_cb_next(it)) { - const PubSubItem* item = list_pubsub_cb_cref(it); + furi_check(osMutexAcquire(pubsub->mutex, osWaitForever) == osOK); + bool result = false; - // if the iterator is equal to our element - if(item == pubsub_id) { - list_pubsub_cb_remove(pubsub_id->self->items, it); - result = true; - break; - } + // iterate over items + FuriPubSubSubscriptionList_it_t it; + for(FuriPubSubSubscriptionList_it(it, pubsub->items); !FuriPubSubSubscriptionList_end_p(it); + FuriPubSubSubscriptionList_next(it)) { + const FuriPubSubSubscription* item = FuriPubSubSubscriptionList_cref(it); + + // if the iterator is equal to our element + if(item == pubsub_subscription) { + FuriPubSubSubscriptionList_remove(pubsub->items, it); + result = true; + break; } - - osMutexRelease(pubsub_id->self->mutex); - return result; - } else { - return false; } + + furi_check(osMutexRelease(pubsub->mutex) == osOK); + furi_check(result); } -bool notify_pubsub(PubSub* pubsub, void* arg) { - if(osMutexAcquire(pubsub->mutex, osWaitForever) == osOK) { - // iterate over subscribers - list_pubsub_cb_it_t it; - for(list_pubsub_cb_it(it, pubsub->items); !list_pubsub_cb_end_p(it); - list_pubsub_cb_next(it)) { - const PubSubItem* item = list_pubsub_cb_cref(it); - item->cb(arg, item->ctx); - } +void furi_pubsub_publish(FuriPubSub* pubsub, void* message) { + furi_check(osMutexAcquire(pubsub->mutex, osWaitForever) == osOK); - osMutexRelease(pubsub->mutex); - return true; - } else { - return false; + // iterate over subscribers + FuriPubSubSubscriptionList_it_t it; + for(FuriPubSubSubscriptionList_it(it, pubsub->items); !FuriPubSubSubscriptionList_end_p(it); + FuriPubSubSubscriptionList_next(it)) { + const FuriPubSubSubscription* item = FuriPubSubSubscriptionList_cref(it); + item->callback(message, item->callback_context); } + + furi_check(osMutexRelease(pubsub->mutex) == osOK); } diff --git a/core/furi/pubsub.h b/core/furi/pubsub.h index 2f440e1c..446d423f 100644 --- a/core/furi/pubsub.h +++ b/core/furi/pubsub.h @@ -1,95 +1,64 @@ #pragma once -#include "cmsis_os.h" -#include "m-list.h" - #ifdef __cplusplus extern "C" { #endif -/** -== PubSub == +/** FuriPubSub Callback type */ +typedef void (*FuriPubSubCallback)(const void* message, void* context); - * PubSub allows users to subscribe on notifies and notify subscribers. - * Notifier side can pass `void*` arg to subscriber callback, - * and also subscriber can set `void*` context pointer that pass into - * callback (you can see callback signature below). +/** FuriPubSub type */ +typedef struct FuriPubSub FuriPubSub; + +/** FuriPubSubSubscription type */ +typedef struct FuriPubSubSubscription FuriPubSubSubscription; + +/** Allocate FuriPubSub + * + * Reentrable, Not threadsafe, one owner + * + * @return pointer to FuriPubSub instance */ +FuriPubSub* furi_pubsub_alloc(); -typedef void (*PubSubCallback)(const void*, void*); -typedef struct PubSubType PubSub; - -typedef struct { - PubSubCallback cb; - void* ctx; - PubSub* self; -} PubSubItem; - -LIST_DEF(list_pubsub_cb, PubSubItem, M_POD_OPLIST); - -struct PubSubType { - list_pubsub_cb_t items; - osMutexId_t mutex; -}; - -/** - * To create PubSub you should create PubSub instance and call `init_pubsub`. +/** Free FuriPubSub + * + * @param pubsub FuriPubSub instance */ -bool init_pubsub(PubSub* pubsub); +void furi_pubsub_free(FuriPubSub* pubsub); -/** - * Since we use dynamic memory - we must explicity delete pubsub +/** Subscribe to FuriPubSub + * + * Threadsafe, Reentrable + * + * @param pubsub pointer to FuriPubSub instance + * @param[in] callback The callback + * @param callback_context The callback context + * + * @return pointer to FuriPubSubSubscription instance */ -bool delete_pubsub(PubSub* pubsub); +FuriPubSubSubscription* + furi_pubsub_subscribe(FuriPubSub* pubsub, FuriPubSubCallback callback, void* callback_context); -/** - * Use `subscribe_pubsub` to register your callback. +/** Unsubscribe from FuriPubSub + * + * No use of `pubsub_subscription` allowed after call of this method + * Threadsafe, Reentrable. + * + * @param pubsub pointer to FuriPubSub instance + * @param pubsub_subscription pointer to FuriPubSubSubscription instance */ -PubSubItem* subscribe_pubsub(PubSub* pubsub, PubSubCallback cb, void* ctx); +void furi_pubsub_unsubscribe(FuriPubSub* pubsub, FuriPubSubSubscription* pubsub_subscription); -/** - * Use `unsubscribe_pubsub` to unregister callback. +/** Publish message to FuriPubSub + * + * Threadsafe, Reentrable. + * + * @param pubsub pointer to FuriPubSub instance + * @param message message pointer to publish */ -bool unsubscribe_pubsub(PubSubItem* pubsub_id); - -/** - * Use `notify_pubsub` to notify subscribers. - */ -bool notify_pubsub(PubSub* pubsub, void* arg); +void furi_pubsub_publish(FuriPubSub* pubsub, void* message); #ifdef __cplusplus } #endif - -/* - -```C -// MANIFEST -// name="test" -// stack=128 - -void example_pubsub_handler(void* arg, void* ctx) { - printf("get %d from %s\n", *(uint32_t*)arg, (const char*)ctx); -} - -void pubsub_test() { - const char* app_name = "test app"; - - PubSub example_pubsub; - init_pubsub(&example_pubsub); - - if(!subscribe_pubsub(&example_pubsub, example_pubsub_handler, (void*)app_name)) { - printf("critical error\n"); - flapp_exit(NULL); - } - - uint32_t counter = 0; - while(1) { - notify_pubsub(&example_pubsub, (void*)&counter); - counter++; - - osDelay(100); - } -} -``` -*/ diff --git a/core/furi/record.c b/core/furi/record.c index 85d196c0..29e33caf 100644 --- a/core/furi/record.c +++ b/core/furi/record.c @@ -84,8 +84,8 @@ bool furi_record_destroy(const char* name) { FuriRecordData* record_data = FuriRecordDataDict_get(furi_record->records, name_str); furi_assert(record_data); if(record_data->holders_count == 0) { - FuriRecordDataDict_erase(furi_record->records, name_str); furi_check(osOK == osEventFlagsDelete(record_data->flags)); + FuriRecordDataDict_erase(furi_record->records, name_str); ret = true; } diff --git a/core/furi/stdglue.c b/core/furi/stdglue.c index 4755c7ab..bd4b11c9 100644 --- a/core/furi/stdglue.c +++ b/core/furi/stdglue.c @@ -2,6 +2,9 @@ #include "check.h" #include "memmgr.h" +#include +#include + #include #include diff --git a/firmware/targets/f6/furi-hal/furi-hal-spi.c b/firmware/targets/f6/furi-hal/furi-hal-spi.c index c925abee..805b8dfb 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-spi.c +++ b/firmware/targets/f6/furi-hal/furi-hal-spi.c @@ -133,7 +133,7 @@ const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) { furi_assert(device_id < FuriHalSpiDeviceIdMax); const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id]; - assert(device); + furi_assert(device); furi_hal_spi_bus_lock(device->bus); furi_hal_spi_device_configure(device); diff --git a/firmware/targets/f6/furi-hal/furi-hal-subghz.c b/firmware/targets/f6/furi-hal/furi-hal-subghz.c index e25c40d1..cd610cb2 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-subghz.c +++ b/firmware/targets/f6/furi-hal/furi-hal-subghz.c @@ -676,7 +676,7 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) { } uint32_t duration = level_duration_get_duration(ld); - assert(duration > 0); + furi_assert(duration > 0); *buffer = duration; buffer++; samples--; diff --git a/firmware/targets/f7/furi-hal/furi-hal-spi.c b/firmware/targets/f7/furi-hal/furi-hal-spi.c index c925abee..805b8dfb 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-spi.c +++ b/firmware/targets/f7/furi-hal/furi-hal-spi.c @@ -133,7 +133,7 @@ const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) { furi_assert(device_id < FuriHalSpiDeviceIdMax); const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id]; - assert(device); + furi_assert(device); furi_hal_spi_bus_lock(device->bus); furi_hal_spi_device_configure(device); diff --git a/firmware/targets/f7/furi-hal/furi-hal-subghz.c b/firmware/targets/f7/furi-hal/furi-hal-subghz.c index e25c40d1..cd610cb2 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-subghz.c +++ b/firmware/targets/f7/furi-hal/furi-hal-subghz.c @@ -676,7 +676,7 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) { } uint32_t duration = level_duration_get_duration(ld); - assert(duration > 0); + furi_assert(duration > 0); *buffer = duration; buffer++; samples--; diff --git a/lib/common-api/task-control-block.h b/lib/common-api/task-control-block.h index 8d7b9b91..32d2edec 100644 --- a/lib/common-api/task-control-block.h +++ b/lib/common-api/task-control-block.h @@ -1,7 +1,7 @@ #pragma once -#include "FreeRTOS.h" - +#include +#include typedef struct /* The old naming convention is used to prevent breaking kernel aware debuggers. */ { diff --git a/lib/irda/worker/irda_worker.c b/lib/irda/worker/irda_worker.c index 98b091f4..58b6ef5a 100644 --- a/lib/irda/worker/irda_worker.c +++ b/lib/irda/worker/irda_worker.c @@ -7,6 +7,7 @@ #include #include #include + #include #include