mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2024-12-25 06:13:14 +03:00
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 <alleteam@gmail.com>
This commit is contained in:
parent
b397442d89
commit
e9e76e144c
@ -69,8 +69,8 @@ Bt* bt_alloc() {
|
|||||||
|
|
||||||
// Power
|
// Power
|
||||||
bt->power = furi_record_open("power");
|
bt->power = furi_record_open("power");
|
||||||
PubSub* power_pubsub = power_get_pubsub(bt->power);
|
FuriPubSub* power_pubsub = power_get_pubsub(bt->power);
|
||||||
subscribe_pubsub(power_pubsub, bt_battery_level_changed_callback, bt);
|
furi_pubsub_subscribe(power_pubsub, bt_battery_level_changed_callback, bt);
|
||||||
|
|
||||||
// RPC
|
// RPC
|
||||||
bt->rpc = furi_record_open("rpc");
|
bt->rpc = furi_record_open("rpc");
|
||||||
|
@ -410,7 +410,7 @@ Gui* gui_alloc() {
|
|||||||
gui->input_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL);
|
gui->input_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL);
|
||||||
gui->input_events = furi_record_open("input_events");
|
gui->input_events = furi_record_open("input_events");
|
||||||
furi_check(gui->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
|
// Cli
|
||||||
gui->cli = furi_record_open("cli");
|
gui->cli = furi_record_open("cli");
|
||||||
cli_add_command(
|
cli_add_command(
|
||||||
|
@ -50,7 +50,7 @@ struct Gui {
|
|||||||
|
|
||||||
// Input
|
// Input
|
||||||
osMessageQueueId_t input_queue;
|
osMessageQueueId_t input_queue;
|
||||||
PubSub* input_events;
|
FuriPubSub* input_events;
|
||||||
uint8_t ongoing_input;
|
uint8_t ongoing_input;
|
||||||
ViewPort* ongoing_input_view_port;
|
ViewPort* ongoing_input_view_port;
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include "icon_i.h"
|
#include "icon_i.h"
|
||||||
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <timers.h>
|
|
||||||
|
|
||||||
IconAnimation* icon_animation_alloc(const Icon* icon) {
|
IconAnimation* icon_animation_alloc(const Icon* icon) {
|
||||||
furi_assert(icon);
|
furi_assert(icon);
|
||||||
|
@ -28,11 +28,11 @@ void input_press_timer_callback(void* arg) {
|
|||||||
input_pin->press_counter++;
|
input_pin->press_counter++;
|
||||||
if(input_pin->press_counter == INPUT_LONG_PRESS_COUNTS) {
|
if(input_pin->press_counter == INPUT_LONG_PRESS_COUNTS) {
|
||||||
event.type = InputTypeLong;
|
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) {
|
} else if(input_pin->press_counter > INPUT_LONG_PRESS_COUNTS) {
|
||||||
input_pin->press_counter--;
|
input_pin->press_counter--;
|
||||||
event.type = InputTypeRepeat;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
// Publish input event
|
// Publish input event
|
||||||
notify_pubsub(&input->event_pubsub, &event);
|
furi_pubsub_publish(input->event_pubsub, &event);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* input_get_key_name(InputKey key) {
|
const char* input_get_key_name(InputKey key) {
|
||||||
@ -120,8 +120,8 @@ const char* input_get_type_name(InputType type) {
|
|||||||
int32_t input_srv() {
|
int32_t input_srv() {
|
||||||
input = furi_alloc(sizeof(Input));
|
input = furi_alloc(sizeof(Input));
|
||||||
input->thread = osThreadGetId();
|
input->thread = osThreadGetId();
|
||||||
init_pubsub(&input->event_pubsub);
|
input->event_pubsub = furi_pubsub_alloc();
|
||||||
furi_record_create("input_events", &input->event_pubsub);
|
furi_record_create("input_events", input->event_pubsub);
|
||||||
|
|
||||||
input->cli = furi_record_open("cli");
|
input->cli = furi_record_open("cli");
|
||||||
if(input->cli) {
|
if(input->cli) {
|
||||||
@ -168,14 +168,14 @@ int32_t input_srv() {
|
|||||||
input_timer_stop(input->pin_states[i].press_timer);
|
input_timer_stop(input->pin_states[i].press_timer);
|
||||||
if(input->pin_states[i].press_counter < INPUT_LONG_PRESS_COUNTS) {
|
if(input->pin_states[i].press_counter < INPUT_LONG_PRESS_COUNTS) {
|
||||||
event.type = InputTypeShort;
|
event.type = InputTypeShort;
|
||||||
notify_pubsub(&input->event_pubsub, &event);
|
furi_pubsub_publish(input->event_pubsub, &event);
|
||||||
}
|
}
|
||||||
input->pin_states[i].press_counter = 0;
|
input->pin_states[i].press_counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send Press/Release event
|
// Send Press/Release event
|
||||||
event.type = input->pin_states[i].state ? InputTypePress : InputTypeRelease;
|
event.type = input->pin_states[i].state ? InputTypePress : InputTypeRelease;
|
||||||
notify_pubsub(&input->event_pubsub, &event);
|
furi_pubsub_publish(input->event_pubsub, &event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ typedef enum {
|
|||||||
InputTypeRepeat, /**< Repeat event, emmited with INPUT_REPEATE_PRESS period after InputTypeLong event */
|
InputTypeRepeat, /**< Repeat event, emmited with INPUT_REPEATE_PRESS period after InputTypeLong event */
|
||||||
} InputType;
|
} InputType;
|
||||||
|
|
||||||
/** Input Event, dispatches with PubSub */
|
/** Input Event, dispatches with FuriPubSub */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t sequence;
|
uint32_t sequence;
|
||||||
InputKey key;
|
InputKey key;
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include <FreeRTOS.h>
|
|
||||||
#include <timers.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -35,7 +33,7 @@ typedef struct {
|
|||||||
/** Input state */
|
/** Input state */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
osThreadId_t thread;
|
osThreadId_t thread;
|
||||||
PubSub event_pubsub;
|
FuriPubSub* event_pubsub;
|
||||||
InputPinState* pin_states;
|
InputPinState* pin_states;
|
||||||
Cli* cli;
|
Cli* cli;
|
||||||
volatile uint32_t counter;
|
volatile uint32_t counter;
|
||||||
|
4
applications/loader/loader.c
Executable file → Normal file
4
applications/loader/loader.c
Executable file → Normal file
@ -140,7 +140,7 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con
|
|||||||
Loader* instance = context;
|
Loader* instance = context;
|
||||||
|
|
||||||
if(thread_state == FuriThreadStateRunning) {
|
if(thread_state == FuriThreadStateRunning) {
|
||||||
instance->free_heap_size = xPortGetFreeHeapSize();
|
instance->free_heap_size = memmgr_get_free_heap();
|
||||||
} else if(thread_state == FuriThreadStateStopped) {
|
} else if(thread_state == FuriThreadStateStopped) {
|
||||||
/*
|
/*
|
||||||
* Current Leak Sanitizer assumes that memory is allocated and freed
|
* 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.
|
* both values should be taken into account.
|
||||||
*/
|
*/
|
||||||
delay(20);
|
delay(20);
|
||||||
int heap_diff = instance->free_heap_size - xPortGetFreeHeapSize();
|
int heap_diff = instance->free_heap_size - memmgr_get_free_heap();
|
||||||
FURI_LOG_I(
|
FURI_LOG_I(
|
||||||
LOADER_LOG_TAG,
|
LOADER_LOG_TAG,
|
||||||
"Application thread stopped. Heap allocation balance: %d. Thread allocation balance: %d.",
|
"Application thread stopped. Heap allocation balance: %d. Thread allocation balance: %d.",
|
||||||
|
@ -427,7 +427,7 @@ static NotificationApp* notification_app_alloc() {
|
|||||||
|
|
||||||
// display backlight control
|
// display backlight control
|
||||||
app->event_record = furi_record_open("input_events");
|
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);
|
notification_message(app, &sequence_display_on);
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
|
@ -44,7 +44,7 @@ typedef struct {
|
|||||||
|
|
||||||
struct NotificationApp {
|
struct NotificationApp {
|
||||||
osMessageQueueId_t queue;
|
osMessageQueueId_t queue;
|
||||||
PubSub* event_record;
|
FuriPubSub* event_record;
|
||||||
osTimerId_t display_timer;
|
osTimerId_t display_timer;
|
||||||
|
|
||||||
NotificationLedLayer display;
|
NotificationLedLayer display;
|
||||||
|
@ -31,7 +31,7 @@ Power* power_alloc() {
|
|||||||
power->gui = furi_record_open("gui");
|
power->gui = furi_record_open("gui");
|
||||||
|
|
||||||
// Pubsub
|
// Pubsub
|
||||||
init_pubsub(&power->event_pubsub);
|
power->event_pubsub = furi_pubsub_alloc();
|
||||||
|
|
||||||
// State initialization
|
// State initialization
|
||||||
power->state = PowerStateNotCharging;
|
power->state = PowerStateNotCharging;
|
||||||
@ -60,10 +60,6 @@ Power* power_alloc() {
|
|||||||
void power_free(Power* power) {
|
void power_free(Power* power) {
|
||||||
furi_assert(power);
|
furi_assert(power);
|
||||||
|
|
||||||
// Records
|
|
||||||
furi_record_close("notification");
|
|
||||||
furi_record_close("gui");
|
|
||||||
|
|
||||||
// Gui
|
// Gui
|
||||||
view_dispatcher_remove_view(power->view_dispatcher, PowerViewOff);
|
view_dispatcher_remove_view(power->view_dispatcher, PowerViewOff);
|
||||||
power_off_free(power->power_off);
|
power_off_free(power->power_off);
|
||||||
@ -73,6 +69,14 @@ void power_free(Power* power) {
|
|||||||
|
|
||||||
// State
|
// State
|
||||||
osMutexDelete(power->info_mtx);
|
osMutexDelete(power->info_mtx);
|
||||||
|
|
||||||
|
// FuriPubSub
|
||||||
|
furi_pubsub_free(power->event_pubsub);
|
||||||
|
|
||||||
|
// Records
|
||||||
|
furi_record_close("notification");
|
||||||
|
furi_record_close("gui");
|
||||||
|
|
||||||
free(power);
|
free(power);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,14 +87,14 @@ static void power_check_charging_state(Power* power) {
|
|||||||
notification_internal_message(power->notification, &sequence_charged);
|
notification_internal_message(power->notification, &sequence_charged);
|
||||||
power->state = PowerStateCharged;
|
power->state = PowerStateCharged;
|
||||||
power->event.type = PowerEventTypeFullyCharged;
|
power->event.type = PowerEventTypeFullyCharged;
|
||||||
notify_pubsub(&power->event_pubsub, &power->event);
|
furi_pubsub_publish(power->event_pubsub, &power->event);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(power->state != PowerStateCharging) {
|
if(power->state != PowerStateCharging) {
|
||||||
notification_internal_message(power->notification, &sequence_charging);
|
notification_internal_message(power->notification, &sequence_charging);
|
||||||
power->state = PowerStateCharging;
|
power->state = PowerStateCharging;
|
||||||
power->event.type = PowerEventTypeStartCharging;
|
power->event.type = PowerEventTypeStartCharging;
|
||||||
notify_pubsub(&power->event_pubsub, &power->event);
|
furi_pubsub_publish(power->event_pubsub, &power->event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -98,7 +102,7 @@ static void power_check_charging_state(Power* power) {
|
|||||||
notification_internal_message(power->notification, &sequence_not_charging);
|
notification_internal_message(power->notification, &sequence_not_charging);
|
||||||
power->state = PowerStateNotCharging;
|
power->state = PowerStateNotCharging;
|
||||||
power->event.type = PowerEventTypeStopCharging;
|
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->battery_level = power->info.charge;
|
||||||
power->event.type = PowerEventTypeBatteryLevelChanged;
|
power->event.type = PowerEventTypeBatteryLevelChanged;
|
||||||
power->event.data.battery_level = power->battery_level;
|
power->event.data.battery_level = power->battery_level;
|
||||||
notify_pubsub(&power->event_pubsub, &power->event);
|
furi_pubsub_publish(power->event_pubsub, &power->event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,4 +62,4 @@ void power_get_info(Power* power, PowerInfo* info);
|
|||||||
/** Get power event pubsub handler
|
/** Get power event pubsub handler
|
||||||
* @param power - Power instance
|
* @param power - Power instance
|
||||||
*/
|
*/
|
||||||
PubSub* power_get_pubsub(Power* power);
|
FuriPubSub* power_get_pubsub(Power* power);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "power_i.h"
|
#include "power_i.h"
|
||||||
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include "furi-hal-power.h"
|
#include "furi-hal-power.h"
|
||||||
#include "furi-hal-bootloader.h"
|
#include "furi-hal-bootloader.h"
|
||||||
@ -30,7 +31,7 @@ void power_get_info(Power* power, PowerInfo* info) {
|
|||||||
osMutexRelease(power->info_mtx);
|
osMutexRelease(power->info_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
PubSub* power_get_pubsub(Power* power) {
|
FuriPubSub* power_get_pubsub(Power* power) {
|
||||||
furi_assert(power);
|
furi_assert(power);
|
||||||
return &power->event_pubsub;
|
return power->event_pubsub;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ struct Power {
|
|||||||
ViewPort* battery_view_port;
|
ViewPort* battery_view_port;
|
||||||
Gui* gui;
|
Gui* gui;
|
||||||
NotificationApp* notification;
|
NotificationApp* notification;
|
||||||
PubSub event_pubsub;
|
FuriPubSub* event_pubsub;
|
||||||
PowerEvent event;
|
PowerEvent event;
|
||||||
|
|
||||||
PowerState state;
|
PowerState state;
|
||||||
|
@ -113,9 +113,9 @@ void rpc_system_gui_send_input_event_request_process(const PB_Main* request, voi
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PubSub* input_events = furi_record_open("input_events");
|
FuriPubSub* input_events = furi_record_open("input_events");
|
||||||
furi_check(input_events);
|
furi_check(input_events);
|
||||||
notify_pubsub(input_events, &event);
|
furi_pubsub_publish(input_events, &event);
|
||||||
furi_record_close("input_events");
|
furi_record_close("input_events");
|
||||||
rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK);
|
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_handler.message_handler = rpc_system_gui_send_input_event_request_process;
|
||||||
rpc_add_handler(rpc, PB_Main_gui_send_input_event_request_tag, &rpc_handler);
|
rpc_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) {
|
void rpc_system_gui_free(void* ctx) {
|
||||||
|
furi_assert(ctx);
|
||||||
RpcGuiSystem* rpc_gui = ctx;
|
RpcGuiSystem* rpc_gui = ctx;
|
||||||
|
furi_assert(rpc_gui->gui);
|
||||||
gui_set_framebuffer_callback(rpc_gui->gui, NULL, NULL);
|
gui_set_framebuffer_callback(rpc_gui->gui, NULL, NULL);
|
||||||
furi_record_close("gui");
|
furi_record_close("gui");
|
||||||
free(rpc_gui);
|
free(rpc_gui);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "rpc.h"
|
#include "rpc.h"
|
||||||
|
#include "storage/filesystem-api-defines.h"
|
||||||
#include <pb.h>
|
#include <pb.h>
|
||||||
#include <pb_decode.h>
|
#include <pb_decode.h>
|
||||||
#include <pb_encode.h>
|
#include <pb_encode.h>
|
||||||
@ -29,3 +30,5 @@ void rpc_system_gui_free(void* ctx);
|
|||||||
|
|
||||||
void rpc_print_message(const PB_Main* message);
|
void rpc_print_message(const PB_Main* message);
|
||||||
void rpc_cli_command_start_session(Cli* cli, string_t args, void* context);
|
void rpc_cli_command_start_session(Cli* cli, string_t args, void* context);
|
||||||
|
|
||||||
|
PB_CommandStatus rpc_system_storage_get_error(FS_Error fs_error);
|
@ -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;
|
PB_CommandStatus pb_error;
|
||||||
switch(fs_error) {
|
switch(fs_error) {
|
||||||
case FSE_OK:
|
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));
|
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) {
|
static void rpc_system_storage_list_root(const PB_Main* request, void* context) {
|
||||||
RpcStorageSystem* rpc_storage = context;
|
RpcStorageSystem* rpc_storage = context;
|
||||||
const char* hard_coded_dirs[] = {"any", "int", "ext"};
|
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 = {
|
PB_Main response = {
|
||||||
.command_id = request->command_id,
|
.command_id = request->command_id,
|
||||||
.has_next = false,
|
.has_next = false,
|
||||||
.which_content = PB_Main_storage_list_request_tag,
|
.which_content = PB_Main_storage_list_response_tag,
|
||||||
.command_status = PB_CommandStatus_OK,
|
.command_status = PB_CommandStatus_OK,
|
||||||
};
|
};
|
||||||
PB_Storage_ListResponse* list = &response.content.storage_list_response;
|
PB_Storage_ListResponse* list = &response.content.storage_list_response;
|
||||||
response.which_content = PB_Main_storage_list_response_tag;
|
|
||||||
|
|
||||||
bool finish = false;
|
bool finish = false;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -434,6 +467,9 @@ void* rpc_system_storage_alloc(Rpc* rpc) {
|
|||||||
.context = rpc_storage,
|
.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_handler.message_handler = rpc_system_storage_list_process;
|
||||||
rpc_add_handler(rpc, PB_Main_storage_list_request_tag, &rpc_handler);
|
rpc_add_handler(rpc, PB_Main_storage_list_request_tag, &rpc_handler);
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include "filesystem-api-internal.h"
|
#include "filesystem-api-internal.h"
|
||||||
#include <m-string.h>
|
#include <m-string.h>
|
||||||
#include <m-array.h>
|
#include <m-array.h>
|
||||||
|
#include <m-list.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi-hal.h>
|
#include <furi-hal.h>
|
||||||
#include <stream_buffer.h>
|
#include <stream_buffer.h>
|
||||||
|
|
||||||
#include <lib/toolbox/args.h>
|
#include <lib/toolbox/args.h>
|
||||||
#include <lib/subghz/subghz_parser.h>
|
#include <lib/subghz/subghz_parser.h>
|
||||||
#include <lib/subghz/subghz_keystore.h>
|
#include <lib/subghz/subghz_keystore.h>
|
||||||
|
@ -16,39 +16,30 @@ void test_pubsub_handler(const void* arg, void* ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void test_furi_pubsub() {
|
void test_furi_pubsub() {
|
||||||
bool result;
|
FuriPubSub* test_pubsub = NULL;
|
||||||
PubSub test_pubsub;
|
FuriPubSubSubscription* test_pubsub_subscription = NULL;
|
||||||
PubSubItem* test_pubsub_item;
|
|
||||||
|
|
||||||
// init pubsub case
|
// init pubsub case
|
||||||
result = init_pubsub(&test_pubsub);
|
test_pubsub = furi_pubsub_alloc();
|
||||||
mu_assert(result, "init pubsub failed");
|
mu_assert_pointers_not_eq(test_pubsub, NULL);
|
||||||
|
|
||||||
// subscribe pubsub case
|
// subscribe pubsub case
|
||||||
test_pubsub_item = subscribe_pubsub(&test_pubsub, test_pubsub_handler, (void*)&context_value);
|
test_pubsub_subscription =
|
||||||
mu_assert_pointers_not_eq(test_pubsub_item, NULL);
|
furi_pubsub_subscribe(test_pubsub, test_pubsub_handler, (void*)&context_value);
|
||||||
|
mu_assert_pointers_not_eq(test_pubsub_subscription, NULL);
|
||||||
|
|
||||||
/// notify pubsub case
|
/// notify pubsub case
|
||||||
result = notify_pubsub(&test_pubsub, (void*)¬ify_value_0);
|
furi_pubsub_publish(test_pubsub, (void*)¬ify_value_0);
|
||||||
mu_assert(result, "notify pubsub failed");
|
|
||||||
mu_assert_int_eq(pubsub_value, notify_value_0);
|
mu_assert_int_eq(pubsub_value, notify_value_0);
|
||||||
mu_assert_int_eq(pubsub_context_value, context_value);
|
mu_assert_int_eq(pubsub_context_value, context_value);
|
||||||
|
|
||||||
// unsubscribe pubsub case
|
// unsubscribe pubsub case
|
||||||
result = unsubscribe_pubsub(test_pubsub_item);
|
furi_pubsub_unsubscribe(test_pubsub, test_pubsub_subscription);
|
||||||
mu_assert(result, "unsubscribe pubsub failed");
|
|
||||||
|
|
||||||
result = unsubscribe_pubsub(test_pubsub_item);
|
|
||||||
mu_assert(!result, "unsubscribe pubsub not failed");
|
|
||||||
|
|
||||||
/// notify unsubscribed pubsub case
|
/// notify unsubscribed pubsub case
|
||||||
result = notify_pubsub(&test_pubsub, (void*)¬ify_value_1);
|
furi_pubsub_publish(test_pubsub, (void*)¬ify_value_1);
|
||||||
mu_assert(result, "notify pubsub failed");
|
|
||||||
mu_assert_int_not_eq(pubsub_value, notify_value_1);
|
mu_assert_int_not_eq(pubsub_value, notify_value_1);
|
||||||
|
|
||||||
// delete pubsub case
|
// delete pubsub case
|
||||||
result = delete_pubsub(&test_pubsub);
|
furi_pubsub_free(test_pubsub);
|
||||||
mu_assert(result, "unsubscribe pubsub failed");
|
|
||||||
|
|
||||||
// TODO test case that the pubsub_delete will remove pubsub from heap
|
|
||||||
}
|
}
|
@ -218,6 +218,9 @@ static void test_rpc_create_simple_message(
|
|||||||
message->which_content = tag;
|
message->which_content = tag;
|
||||||
message->has_next = false;
|
message->has_next = false;
|
||||||
switch(tag) {
|
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:
|
case PB_Main_storage_list_request_tag:
|
||||||
message->content.storage_list_request.path = str_copy;
|
message->content.storage_list_request.path = str_copy;
|
||||||
break;
|
break;
|
||||||
@ -369,6 +372,19 @@ static void test_rpc_compare_messages(PB_Main* result, PB_Main* expected) {
|
|||||||
mu_check(result_locked == expected_locked);
|
mu_check(result_locked == expected_locked);
|
||||||
break;
|
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: {
|
case PB_Main_storage_read_response_tag: {
|
||||||
bool result_has_msg_file = result->content.storage_read_response.has_file;
|
bool result_has_msg_file = result->content.storage_read_response.has_file;
|
||||||
bool expected_has_msg_file = expected->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 = {
|
PB_Main response = {
|
||||||
.command_id = command_id,
|
.command_id = command_id,
|
||||||
.has_next = false,
|
.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 */
|
/* other fields (e.g. msg_files ptrs) explicitly initialized by 0 */
|
||||||
};
|
};
|
||||||
PB_Storage_ListResponse* list = &response.content.storage_list_response;
|
PB_Storage_ListResponse* list = &response.content.storage_list_response;
|
||||||
response.which_content = PB_Main_storage_list_response_tag;
|
|
||||||
|
|
||||||
bool finish = false;
|
bool finish = false;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -649,9 +664,8 @@ static bool test_is_exists(const char* path) {
|
|||||||
Storage* fs_api = furi_record_open("storage");
|
Storage* fs_api = furi_record_open("storage");
|
||||||
FileInfo fileinfo;
|
FileInfo fileinfo;
|
||||||
FS_Error result = storage_common_stat(fs_api, path, &fileinfo);
|
FS_Error result = storage_common_stat(fs_api, path, &fileinfo);
|
||||||
|
|
||||||
furi_check((result == FSE_OK) || (result == FSE_NOT_EXIST));
|
furi_check((result == FSE_OK) || (result == FSE_NOT_EXIST));
|
||||||
|
furi_record_close("storage");
|
||||||
return result == FSE_OK;
|
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));
|
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) {
|
MU_TEST(test_storage_read) {
|
||||||
test_create_file(TEST_DIR "empty.txt", 0);
|
test_create_file(TEST_DIR "empty.txt", 0);
|
||||||
test_create_file(TEST_DIR "file1.txt", 1);
|
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_TEST_SUITE(test_rpc_storage) {
|
||||||
MU_SUITE_CONFIGURE(&test_rpc_storage_setup, &test_rpc_storage_teardown);
|
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_list);
|
||||||
MU_RUN_TEST(test_storage_read);
|
MU_RUN_TEST(test_storage_read);
|
||||||
MU_RUN_TEST(test_storage_write_read);
|
MU_RUN_TEST(test_storage_write_read);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "m-string.h"
|
#include "m-string.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi-hal.h>
|
#include <furi-hal.h>
|
||||||
|
@ -78,6 +78,8 @@ typedef struct _PB_Main {
|
|||||||
PB_Gui_StopScreenStreamRequest gui_stop_screen_stream_request;
|
PB_Gui_StopScreenStreamRequest gui_stop_screen_stream_request;
|
||||||
PB_Gui_ScreenStreamFrame gui_screen_stream_frame;
|
PB_Gui_ScreenStreamFrame gui_screen_stream_frame;
|
||||||
PB_Gui_SendInputEventRequest gui_send_input_event_request;
|
PB_Gui_SendInputEventRequest gui_send_input_event_request;
|
||||||
|
PB_Storage_StatRequest storage_stat_request;
|
||||||
|
PB_Storage_StatResponse storage_stat_response;
|
||||||
} content;
|
} content;
|
||||||
} PB_Main;
|
} PB_Main;
|
||||||
|
|
||||||
@ -124,6 +126,8 @@ extern "C" {
|
|||||||
#define PB_Main_gui_stop_screen_stream_request_tag 21
|
#define PB_Main_gui_stop_screen_stream_request_tag 21
|
||||||
#define PB_Main_gui_screen_stream_frame_tag 22
|
#define PB_Main_gui_screen_stream_frame_tag 22
|
||||||
#define PB_Main_gui_send_input_event_request_tag 23
|
#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 */
|
/* Struct field encoding specification for nanopb */
|
||||||
#define PB_Empty_FIELDLIST(X, a) \
|
#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_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_stop_screen_stream_request,content.gui_stop_screen_stream_request), 21) \
|
||||||
X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_screen_stream_frame,content.gui_screen_stream_frame), 22) \
|
X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_screen_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_CALLBACK NULL
|
||||||
#define PB_Main_DEFAULT NULL
|
#define PB_Main_DEFAULT NULL
|
||||||
#define PB_Main_content_empty_MSGTYPE PB_Empty
|
#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_stop_screen_stream_request_MSGTYPE PB_Gui_StopScreenStreamRequest
|
||||||
#define PB_Main_content_gui_screen_stream_frame_MSGTYPE PB_Gui_ScreenStreamFrame
|
#define PB_Main_content_gui_screen_stream_frame_MSGTYPE PB_Gui_ScreenStreamFrame
|
||||||
#define PB_Main_content_gui_send_input_event_request_MSGTYPE PB_Gui_SendInputEventRequest
|
#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_Empty_msg;
|
||||||
extern const pb_msgdesc_t PB_StopSession_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) */
|
/* Maximum encoded size of messages (where known) */
|
||||||
#define PB_Empty_size 0
|
#define PB_Empty_size 0
|
||||||
#define PB_StopSession_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))
|
#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
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -9,6 +9,12 @@
|
|||||||
PB_BIND(PB_Storage_File, PB_Storage_File, AUTO)
|
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)
|
PB_BIND(PB_Storage_ListRequest, PB_Storage_ListRequest, AUTO)
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,6 +32,10 @@ typedef struct _PB_Storage_ReadRequest {
|
|||||||
char *path;
|
char *path;
|
||||||
} PB_Storage_ReadRequest;
|
} PB_Storage_ReadRequest;
|
||||||
|
|
||||||
|
typedef struct _PB_Storage_StatRequest {
|
||||||
|
char *path;
|
||||||
|
} PB_Storage_StatRequest;
|
||||||
|
|
||||||
typedef struct _PB_Storage_DeleteRequest {
|
typedef struct _PB_Storage_DeleteRequest {
|
||||||
char *path;
|
char *path;
|
||||||
bool recursive;
|
bool recursive;
|
||||||
@ -58,6 +62,11 @@ typedef struct _PB_Storage_ReadResponse {
|
|||||||
PB_Storage_File file;
|
PB_Storage_File file;
|
||||||
} PB_Storage_ReadResponse;
|
} PB_Storage_ReadResponse;
|
||||||
|
|
||||||
|
typedef struct _PB_Storage_StatResponse {
|
||||||
|
bool has_file;
|
||||||
|
PB_Storage_File file;
|
||||||
|
} PB_Storage_StatResponse;
|
||||||
|
|
||||||
typedef struct _PB_Storage_WriteRequest {
|
typedef struct _PB_Storage_WriteRequest {
|
||||||
char *path;
|
char *path;
|
||||||
bool has_file;
|
bool has_file;
|
||||||
@ -77,6 +86,8 @@ extern "C" {
|
|||||||
|
|
||||||
/* Initializer values for message structs */
|
/* Initializer values for message structs */
|
||||||
#define PB_Storage_File_init_default {_PB_Storage_File_FileType_MIN, NULL, 0, NULL}
|
#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_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_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}
|
#define PB_Storage_ReadRequest_init_default {NULL}
|
||||||
@ -87,6 +98,8 @@ extern "C" {
|
|||||||
#define PB_Storage_Md5sumRequest_init_default {NULL}
|
#define PB_Storage_Md5sumRequest_init_default {NULL}
|
||||||
#define PB_Storage_Md5sumResponse_init_default {""}
|
#define PB_Storage_Md5sumResponse_init_default {""}
|
||||||
#define PB_Storage_File_init_zero {_PB_Storage_File_FileType_MIN, NULL, 0, NULL}
|
#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_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_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}
|
#define PB_Storage_ReadRequest_init_zero {NULL}
|
||||||
@ -102,6 +115,7 @@ extern "C" {
|
|||||||
#define PB_Storage_Md5sumRequest_path_tag 1
|
#define PB_Storage_Md5sumRequest_path_tag 1
|
||||||
#define PB_Storage_MkdirRequest_path_tag 1
|
#define PB_Storage_MkdirRequest_path_tag 1
|
||||||
#define PB_Storage_ReadRequest_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_path_tag 1
|
||||||
#define PB_Storage_DeleteRequest_recursive_tag 2
|
#define PB_Storage_DeleteRequest_recursive_tag 2
|
||||||
#define PB_Storage_File_type_tag 1
|
#define PB_Storage_File_type_tag 1
|
||||||
@ -111,6 +125,7 @@ extern "C" {
|
|||||||
#define PB_Storage_Md5sumResponse_md5sum_tag 1
|
#define PB_Storage_Md5sumResponse_md5sum_tag 1
|
||||||
#define PB_Storage_ListResponse_file_tag 1
|
#define PB_Storage_ListResponse_file_tag 1
|
||||||
#define PB_Storage_ReadResponse_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_path_tag 1
|
||||||
#define PB_Storage_WriteRequest_file_tag 2
|
#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_CALLBACK NULL
|
||||||
#define PB_Storage_File_DEFAULT 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) \
|
#define PB_Storage_ListRequest_FIELDLIST(X, a) \
|
||||||
X(a, POINTER, SINGULAR, STRING, path, 1)
|
X(a, POINTER, SINGULAR, STRING, path, 1)
|
||||||
#define PB_Storage_ListRequest_CALLBACK NULL
|
#define PB_Storage_ListRequest_CALLBACK NULL
|
||||||
@ -174,6 +200,8 @@ X(a, STATIC, SINGULAR, STRING, md5sum, 1)
|
|||||||
#define PB_Storage_Md5sumResponse_DEFAULT NULL
|
#define PB_Storage_Md5sumResponse_DEFAULT NULL
|
||||||
|
|
||||||
extern const pb_msgdesc_t PB_Storage_File_msg;
|
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_ListRequest_msg;
|
||||||
extern const pb_msgdesc_t PB_Storage_ListResponse_msg;
|
extern const pb_msgdesc_t PB_Storage_ListResponse_msg;
|
||||||
extern const pb_msgdesc_t PB_Storage_ReadRequest_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 */
|
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||||
#define PB_Storage_File_fields &PB_Storage_File_msg
|
#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_ListRequest_fields &PB_Storage_ListRequest_msg
|
||||||
#define PB_Storage_ListResponse_fields &PB_Storage_ListResponse_msg
|
#define PB_Storage_ListResponse_fields &PB_Storage_ListResponse_msg
|
||||||
#define PB_Storage_ReadRequest_fields &PB_Storage_ReadRequest_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) */
|
/* Maximum encoded size of messages (where known) */
|
||||||
/* PB_Storage_File_size depends on runtime parameters */
|
/* 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_ListRequest_size depends on runtime parameters */
|
||||||
/* PB_Storage_ListResponse_size depends on runtime parameters */
|
/* PB_Storage_ListResponse_size depends on runtime parameters */
|
||||||
/* PB_Storage_ReadRequest_size depends on runtime parameters */
|
/* PB_Storage_ReadRequest_size depends on runtime parameters */
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 76f43b8c6510306d40c006b696d9d1b14a252dc1
|
Subproject commit 0e6d374ab1a12f95a3cd04444376a261e7252db4
|
@ -1,5 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <timers.h>
|
||||||
|
#include <task.h>
|
||||||
|
|
||||||
#include <cmsis_os2.h>
|
#include <cmsis_os2.h>
|
||||||
|
|
||||||
#include <furi/common_defines.h>
|
#include <furi/common_defines.h>
|
||||||
|
@ -1,88 +1,95 @@
|
|||||||
#include "pubsub.h"
|
#include "pubsub.h"
|
||||||
#include <furi.h>
|
#include "memmgr.h"
|
||||||
|
#include "check.h"
|
||||||
|
|
||||||
|
#include <m-list.h>
|
||||||
|
#include <cmsis_os2.h>
|
||||||
|
|
||||||
|
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);
|
pubsub->mutex = osMutexNew(NULL);
|
||||||
if(pubsub->mutex == NULL) return false;
|
furi_assert(pubsub->mutex);
|
||||||
|
|
||||||
// construct list
|
FuriPubSubSubscriptionList_init(pubsub->items);
|
||||||
list_pubsub_cb_init(pubsub->items);
|
|
||||||
|
|
||||||
return true;
|
return pubsub;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool delete_pubsub(PubSub* pubsub) {
|
void furi_pubsub_free(FuriPubSub* pubsub) {
|
||||||
if(osMutexAcquire(pubsub->mutex, osWaitForever) == osOK) {
|
furi_assert(pubsub);
|
||||||
bool result = osMutexDelete(pubsub->mutex) == osOK;
|
|
||||||
list_pubsub_cb_clear(pubsub->items);
|
furi_check(FuriPubSubSubscriptionList_size(pubsub->items) == 0);
|
||||||
return result;
|
|
||||||
} else {
|
FuriPubSubSubscriptionList_clear(pubsub->items);
|
||||||
return false;
|
|
||||||
}
|
furi_check(osMutexDelete(pubsub->mutex) == osOK);
|
||||||
|
|
||||||
|
free(pubsub);
|
||||||
}
|
}
|
||||||
|
|
||||||
PubSubItem* subscribe_pubsub(PubSub* pubsub, PubSubCallback cb, void* ctx) {
|
FuriPubSubSubscription*
|
||||||
if(osMutexAcquire(pubsub->mutex, osWaitForever) == osOK) {
|
furi_pubsub_subscribe(FuriPubSub* pubsub, FuriPubSubCallback callback, void* callback_context) {
|
||||||
// put uninitialized item to the list
|
furi_check(osMutexAcquire(pubsub->mutex, osWaitForever) == osOK);
|
||||||
PubSubItem* item = list_pubsub_cb_push_raw(pubsub->items);
|
// put uninitialized item to the list
|
||||||
|
FuriPubSubSubscription* item = FuriPubSubSubscriptionList_push_raw(pubsub->items);
|
||||||
|
|
||||||
// initialize item
|
// initialize item
|
||||||
item->cb = cb;
|
item->callback = callback;
|
||||||
item->ctx = ctx;
|
item->callback_context = callback_context;
|
||||||
item->self = pubsub;
|
|
||||||
|
|
||||||
// TODO unsubscribe pubsub on app exit
|
furi_check(osMutexRelease(pubsub->mutex) == osOK);
|
||||||
//flapp_on_exit(unsubscribe_pubsub, item);
|
|
||||||
|
|
||||||
osMutexRelease(pubsub->mutex);
|
return item;
|
||||||
|
|
||||||
return item;
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool unsubscribe_pubsub(PubSubItem* pubsub_id) {
|
void furi_pubsub_unsubscribe(FuriPubSub* pubsub, FuriPubSubSubscription* pubsub_subscription) {
|
||||||
if(osMutexAcquire(pubsub_id->self->mutex, osWaitForever) == osOK) {
|
furi_assert(pubsub);
|
||||||
bool result = false;
|
furi_assert(pubsub_subscription);
|
||||||
|
|
||||||
// iterate over items
|
furi_check(osMutexAcquire(pubsub->mutex, osWaitForever) == osOK);
|
||||||
list_pubsub_cb_it_t it;
|
bool result = false;
|
||||||
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);
|
|
||||||
|
|
||||||
// if the iterator is equal to our element
|
// iterate over items
|
||||||
if(item == pubsub_id) {
|
FuriPubSubSubscriptionList_it_t it;
|
||||||
list_pubsub_cb_remove(pubsub_id->self->items, it);
|
for(FuriPubSubSubscriptionList_it(it, pubsub->items); !FuriPubSubSubscriptionList_end_p(it);
|
||||||
result = true;
|
FuriPubSubSubscriptionList_next(it)) {
|
||||||
break;
|
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) {
|
void furi_pubsub_publish(FuriPubSub* pubsub, void* message) {
|
||||||
if(osMutexAcquire(pubsub->mutex, osWaitForever) == osOK) {
|
furi_check(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
osMutexRelease(pubsub->mutex);
|
// iterate over subscribers
|
||||||
return true;
|
FuriPubSubSubscriptionList_it_t it;
|
||||||
} else {
|
for(FuriPubSubSubscriptionList_it(it, pubsub->items); !FuriPubSubSubscriptionList_end_p(it);
|
||||||
return false;
|
FuriPubSubSubscriptionList_next(it)) {
|
||||||
|
const FuriPubSubSubscription* item = FuriPubSubSubscriptionList_cref(it);
|
||||||
|
item->callback(message, item->callback_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
furi_check(osMutexRelease(pubsub->mutex) == osOK);
|
||||||
}
|
}
|
||||||
|
@ -1,95 +1,64 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "cmsis_os.h"
|
|
||||||
#include "m-list.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/** FuriPubSub Callback type */
|
||||||
== PubSub ==
|
typedef void (*FuriPubSubCallback)(const void* message, void* context);
|
||||||
|
|
||||||
* PubSub allows users to subscribe on notifies and notify subscribers.
|
/** FuriPubSub type */
|
||||||
* Notifier side can pass `void*` arg to subscriber callback,
|
typedef struct FuriPubSub FuriPubSub;
|
||||||
* and also subscriber can set `void*` context pointer that pass into
|
|
||||||
* callback (you can see callback signature below).
|
/** 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*);
|
/** Free FuriPubSub
|
||||||
typedef struct PubSubType PubSub;
|
*
|
||||||
|
* @param pubsub FuriPubSub instance
|
||||||
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`.
|
|
||||||
*/
|
*/
|
||||||
bool init_pubsub(PubSub* pubsub);
|
void furi_pubsub_free(FuriPubSub* pubsub);
|
||||||
|
|
||||||
/**
|
/** Subscribe to FuriPubSub
|
||||||
* Since we use dynamic memory - we must explicity delete pubsub
|
*
|
||||||
|
* 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);
|
||||||
|
|
||||||
/**
|
/** Unsubscribe from FuriPubSub
|
||||||
* Use `subscribe_pubsub` to register your callback.
|
*
|
||||||
|
* 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);
|
||||||
|
|
||||||
/**
|
/** Publish message to FuriPubSub
|
||||||
* Use `unsubscribe_pubsub` to unregister callback.
|
*
|
||||||
|
* Threadsafe, Reentrable.
|
||||||
|
*
|
||||||
|
* @param pubsub pointer to FuriPubSub instance
|
||||||
|
* @param message message pointer to publish
|
||||||
*/
|
*/
|
||||||
bool unsubscribe_pubsub(PubSubItem* pubsub_id);
|
void furi_pubsub_publish(FuriPubSub* pubsub, void* message);
|
||||||
|
|
||||||
/**
|
|
||||||
* Use `notify_pubsub` to notify subscribers.
|
|
||||||
*/
|
|
||||||
bool notify_pubsub(PubSub* pubsub, void* arg);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
*/
|
|
||||||
|
@ -84,8 +84,8 @@ bool furi_record_destroy(const char* name) {
|
|||||||
FuriRecordData* record_data = FuriRecordDataDict_get(furi_record->records, name_str);
|
FuriRecordData* record_data = FuriRecordDataDict_get(furi_record->records, name_str);
|
||||||
furi_assert(record_data);
|
furi_assert(record_data);
|
||||||
if(record_data->holders_count == 0) {
|
if(record_data->holders_count == 0) {
|
||||||
FuriRecordDataDict_erase(furi_record->records, name_str);
|
|
||||||
furi_check(osOK == osEventFlagsDelete(record_data->flags));
|
furi_check(osOK == osEventFlagsDelete(record_data->flags));
|
||||||
|
FuriRecordDataDict_erase(furi_record->records, name_str);
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "memmgr.h"
|
#include "memmgr.h"
|
||||||
|
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <task.h>
|
||||||
|
|
||||||
#include <furi-hal.h>
|
#include <furi-hal.h>
|
||||||
#include <m-dict.h>
|
#include <m-dict.h>
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) {
|
|||||||
furi_assert(device_id < FuriHalSpiDeviceIdMax);
|
furi_assert(device_id < FuriHalSpiDeviceIdMax);
|
||||||
|
|
||||||
const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id];
|
const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id];
|
||||||
assert(device);
|
furi_assert(device);
|
||||||
furi_hal_spi_bus_lock(device->bus);
|
furi_hal_spi_bus_lock(device->bus);
|
||||||
furi_hal_spi_device_configure(device);
|
furi_hal_spi_device_configure(device);
|
||||||
|
|
||||||
|
@ -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);
|
uint32_t duration = level_duration_get_duration(ld);
|
||||||
assert(duration > 0);
|
furi_assert(duration > 0);
|
||||||
*buffer = duration;
|
*buffer = duration;
|
||||||
buffer++;
|
buffer++;
|
||||||
samples--;
|
samples--;
|
||||||
|
@ -133,7 +133,7 @@ const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) {
|
|||||||
furi_assert(device_id < FuriHalSpiDeviceIdMax);
|
furi_assert(device_id < FuriHalSpiDeviceIdMax);
|
||||||
|
|
||||||
const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id];
|
const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id];
|
||||||
assert(device);
|
furi_assert(device);
|
||||||
furi_hal_spi_bus_lock(device->bus);
|
furi_hal_spi_bus_lock(device->bus);
|
||||||
furi_hal_spi_device_configure(device);
|
furi_hal_spi_device_configure(device);
|
||||||
|
|
||||||
|
@ -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);
|
uint32_t duration = level_duration_get_duration(ld);
|
||||||
assert(duration > 0);
|
furi_assert(duration > 0);
|
||||||
*buffer = duration;
|
*buffer = duration;
|
||||||
buffer++;
|
buffer++;
|
||||||
samples--;
|
samples--;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "FreeRTOS.h"
|
#include <FreeRTOS.h>
|
||||||
|
#include <task.h>
|
||||||
|
|
||||||
typedef struct /* The old naming convention is used to prevent breaking kernel aware debuggers. */
|
typedef struct /* The old naming convention is used to prevent breaking kernel aware debuggers. */
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
|
||||||
#include <notification/notification-messages.h>
|
#include <notification/notification-messages.h>
|
||||||
#include <stream_buffer.h>
|
#include <stream_buffer.h>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user