Просмотр исходного кода

[FL-2297, FL-2289] Power info command, Validator fixes (#1097)

* Power info command, validator fixes
* strdup in validator, fix memory leak
* furi_hal_crypto fixed again
* FuriHal: limit ARR and CC in speaker hal
* FuriHal: LL_TIM_DisableAllOutputs in speaker stop
* Rpc: fix memory leak in screen streaming
* Get rid of crypto_enable/crypto_disable

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Nikolay Minaylov 3 лет назад
Родитель
Сommit
d635890342

+ 2 - 2
applications/archive/scenes/archive_scene_rename.c

@@ -31,8 +31,8 @@ void archive_scene_rename_on_enter(void* context) {
         MAX_TEXT_INPUT_LEN,
         MAX_TEXT_INPUT_LEN,
         false);
         false);
 
 
-    ValidatorIsFile* validator_is_file =
-        validator_is_file_alloc_init(archive_get_path(archive->browser), archive->file_extension);
+    ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
+        archive_get_path(archive->browser), archive->file_extension, NULL);
     text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
     text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
 
 
     view_dispatcher_switch_to_view(archive->view_dispatcher, ArchiveViewTextInput);
     view_dispatcher_switch_to_view(archive->view_dispatcher, ArchiveViewTextInput);

+ 14 - 2
applications/gui/modules/validators.c

@@ -5,11 +5,19 @@
 struct ValidatorIsFile {
 struct ValidatorIsFile {
     const char* app_path_folder;
     const char* app_path_folder;
     const char* app_extension;
     const char* app_extension;
+    char* current_name;
 };
 };
 
 
 bool validator_is_file_callback(const char* text, string_t error, void* context) {
 bool validator_is_file_callback(const char* text, string_t error, void* context) {
     furi_assert(context);
     furi_assert(context);
     ValidatorIsFile* instance = context;
     ValidatorIsFile* instance = context;
+
+    if(instance->current_name != NULL) {
+        if(strcmp(instance->current_name, text) == 0) {
+            return true;
+        }
+    }
+
     bool ret = true;
     bool ret = true;
     string_t path;
     string_t path;
     string_init_printf(path, "%s/%s%s", instance->app_path_folder, text, instance->app_extension);
     string_init_printf(path, "%s/%s%s", instance->app_path_folder, text, instance->app_extension);
@@ -26,17 +34,21 @@ bool validator_is_file_callback(const char* text, string_t error, void* context)
     return ret;
     return ret;
 }
 }
 
 
-ValidatorIsFile*
-    validator_is_file_alloc_init(const char* app_path_folder, const char* app_extension) {
+ValidatorIsFile* validator_is_file_alloc_init(
+    const char* app_path_folder,
+    const char* app_extension,
+    const char* current_name) {
     ValidatorIsFile* instance = malloc(sizeof(ValidatorIsFile));
     ValidatorIsFile* instance = malloc(sizeof(ValidatorIsFile));
 
 
     instance->app_path_folder = app_path_folder;
     instance->app_path_folder = app_path_folder;
     instance->app_extension = app_extension;
     instance->app_extension = app_extension;
+    instance->current_name = strdup(current_name);
 
 
     return instance;
     return instance;
 }
 }
 
 
 void validator_is_file_free(ValidatorIsFile* instance) {
 void validator_is_file_free(ValidatorIsFile* instance) {
     furi_assert(instance);
     furi_assert(instance);
+    free(instance->current_name);
     free(instance);
     free(instance);
 }
 }

+ 4 - 2
applications/gui/modules/validators.h

@@ -8,8 +8,10 @@ extern "C" {
 #endif
 #endif
 typedef struct ValidatorIsFile ValidatorIsFile;
 typedef struct ValidatorIsFile ValidatorIsFile;
 
 
-ValidatorIsFile*
-    validator_is_file_alloc_init(const char* app_path_folder, const char* app_extension);
+ValidatorIsFile* validator_is_file_alloc_init(
+    const char* app_path_folder,
+    const char* app_extension,
+    const char* current_name);
 
 
 void validator_is_file_free(ValidatorIsFile* instance);
 void validator_is_file_free(ValidatorIsFile* instance);
 
 

+ 1 - 1
applications/ibutton/scene/ibutton_scene_save_name.cpp

@@ -35,7 +35,7 @@ void iButtonSceneSaveName::on_enter(iButtonApp* app) {
         key_name_empty);
         key_name_empty);
 
 
     ValidatorIsFile* validator_is_file =
     ValidatorIsFile* validator_is_file =
-        validator_is_file_alloc_init(app->app_folder, app->app_extension);
+        validator_is_file_alloc_init(app->app_folder, app->app_extension, key_name);
     text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
     text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
 
 
     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewTextInput);
     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewTextInput);

+ 2 - 2
applications/infrared/scene/infrared_app_scene_edit_rename.cpp

@@ -21,8 +21,8 @@ void InfraredAppSceneEditRename::on_enter(InfraredApp* app) {
         enter_name_length = InfraredAppRemoteManager::max_remote_name_length;
         enter_name_length = InfraredAppRemoteManager::max_remote_name_length;
         text_input_set_header_text(text_input, "Name the remote");
         text_input_set_header_text(text_input, "Name the remote");
 
 
-        ValidatorIsFile* validator_is_file =
-            validator_is_file_alloc_init(app->infrared_directory, app->infrared_extension);
+        ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
+            app->infrared_directory, app->infrared_extension, remote_name.c_str());
         text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
         text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
     }
     }
 
 

+ 1 - 1
applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp

@@ -22,7 +22,7 @@ void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool need_restore) {
         key_name_empty);
         key_name_empty);
 
 
     ValidatorIsFile* validator_is_file =
     ValidatorIsFile* validator_is_file =
-        validator_is_file_alloc_init(app->app_folder, app->app_extension);
+        validator_is_file_alloc_init(app->app_folder, app->app_extension, key_name);
     text_input->set_validator(validator_is_file_callback, validator_is_file);
     text_input->set_validator(validator_is_file_callback, validator_is_file);
 
 
     app->view_controller.switch_to<TextInputVM>();
     app->view_controller.switch_to<TextInputVM>();

+ 1 - 1
applications/nfc/scenes/nfc_scene_save_name.c

@@ -30,7 +30,7 @@ void nfc_scene_save_name_on_enter(void* context) {
         dev_name_empty);
         dev_name_empty);
 
 
     ValidatorIsFile* validator_is_file =
     ValidatorIsFile* validator_is_file =
-        validator_is_file_alloc_init(NFC_APP_FOLDER, NFC_APP_EXTENSION);
+        validator_is_file_alloc_init(NFC_APP_FOLDER, NFC_APP_EXTENSION, nfc->dev->dev_name);
     text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
     text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
 
 
     view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput);
     view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput);

+ 14 - 0
applications/power/power_cli.c

@@ -20,6 +20,14 @@ void power_cli_reboot2dfu(Cli* cli, string_t args) {
     power_reboot(PowerBootModeDfu);
     power_reboot(PowerBootModeDfu);
 }
 }
 
 
+static void power_cli_info_callback(const char* key, const char* value, bool last, void* context) {
+    printf("%-24s: %s\r\n", key, value);
+}
+
+void power_cli_info(Cli* cli, string_t args) {
+    furi_hal_power_info_get(power_cli_info_callback, NULL);
+}
+
 void power_cli_debug(Cli* cli, string_t args) {
 void power_cli_debug(Cli* cli, string_t args) {
     furi_hal_power_dump_state();
     furi_hal_power_dump_state();
 }
 }
@@ -52,6 +60,7 @@ static void power_cli_command_print_usage() {
     printf("\toff\t - shutdown power\r\n");
     printf("\toff\t - shutdown power\r\n");
     printf("\treboot\t - reboot\r\n");
     printf("\treboot\t - reboot\r\n");
     printf("\treboot2dfu\t - reboot to dfu bootloader\r\n");
     printf("\treboot2dfu\t - reboot to dfu bootloader\r\n");
+    printf("\tinfo\t - show power info\r\n");
     printf("\tdebug\t - show debug information\r\n");
     printf("\tdebug\t - show debug information\r\n");
     printf("\t5v <0 or 1>\t - enable or disable 5v ext\r\n");
     printf("\t5v <0 or 1>\t - enable or disable 5v ext\r\n");
     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
@@ -84,6 +93,11 @@ void power_cli(Cli* cli, string_t args, void* context) {
             break;
             break;
         }
         }
 
 
+        if(string_cmp_str(cmd, "info") == 0) {
+            power_cli_info(cli, args);
+            break;
+        }
+
         if(string_cmp_str(cmd, "debug") == 0) {
         if(string_cmp_str(cmd, "debug") == 0) {
             power_cli_debug(cli, args);
             power_cli_debug(cli, args);
             break;
             break;

+ 5 - 0
applications/rpc/rpc_cli.c

@@ -4,6 +4,8 @@
 #include <furi_hal.h>
 #include <furi_hal.h>
 #include <semphr.h>
 #include <semphr.h>
 
 
+#define TAG "RpcCli"
+
 typedef struct {
 typedef struct {
     Cli* cli;
     Cli* cli;
     bool session_close_request;
     bool session_close_request;
@@ -38,6 +40,9 @@ static void rpc_session_terminated_callback(void* context) {
 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) {
     Rpc* rpc = context;
     Rpc* rpc = context;
 
 
+    uint32_t mem_before = memmgr_get_free_heap();
+    FURI_LOG_D(TAG, "Free memory %d", mem_before);
+
     furi_hal_usb_lock();
     furi_hal_usb_lock();
     RpcSession* rpc_session = rpc_session_open(rpc);
     RpcSession* rpc_session = rpc_session_open(rpc);
     if(rpc_session == NULL) {
     if(rpc_session == NULL) {

+ 11 - 0
applications/rpc/rpc_gui.c

@@ -346,8 +346,19 @@ void rpc_system_gui_free(void* context) {
     }
     }
 
 
     if(rpc_gui->is_streaming) {
     if(rpc_gui->is_streaming) {
+        rpc_gui->is_streaming = false;
+        // Remove GUI framebuffer callback
         gui_remove_framebuffer_callback(
         gui_remove_framebuffer_callback(
             rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context);
             rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context);
+        // Stop and release worker thread
+        osThreadFlagsSet(
+            furi_thread_get_thread_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagExit);
+        furi_thread_join(rpc_gui->transmit_thread);
+        furi_thread_free(rpc_gui->transmit_thread);
+        // Release frame
+        pb_release(&PB_Main_msg, rpc_gui->transmit_frame);
+        free(rpc_gui->transmit_frame);
+        rpc_gui->transmit_frame = NULL;
     }
     }
     furi_record_close("gui");
     furi_record_close("gui");
     free(rpc_gui);
     free(rpc_gui);

+ 50 - 7
applications/rpc/rpc_system.c

@@ -6,6 +6,11 @@
 
 
 #include "rpc_i.h"
 #include "rpc_i.h"
 
 
+typedef struct {
+    RpcSession* session;
+    PB_Main* response;
+} RpcSystemContext;
+
 static void rpc_system_system_ping_process(const PB_Main* request, void* context) {
 static void rpc_system_system_ping_process(const PB_Main* request, void* context) {
     furi_assert(request);
     furi_assert(request);
     furi_assert(request->which_content == PB_Main_system_ping_request_tag);
     furi_assert(request->which_content == PB_Main_system_ping_request_tag);
@@ -55,11 +60,6 @@ static void rpc_system_system_reboot_process(const PB_Main* request, void* conte
     }
     }
 }
 }
 
 
-typedef struct {
-    RpcSession* session;
-    PB_Main* response;
-} RpcSystemSystemDeviceInfoContext;
-
 static void rpc_system_system_device_info_callback(
 static void rpc_system_system_device_info_callback(
     const char* key,
     const char* key,
     const char* value,
     const char* value,
@@ -67,7 +67,7 @@ static void rpc_system_system_device_info_callback(
     void* context) {
     void* context) {
     furi_assert(key);
     furi_assert(key);
     furi_assert(value);
     furi_assert(value);
-    RpcSystemSystemDeviceInfoContext* ctx = context;
+    RpcSystemContext* ctx = context;
 
 
     char* str_key = strdup(key);
     char* str_key = strdup(key);
     char* str_value = strdup(value);
     char* str_value = strdup(value);
@@ -91,7 +91,7 @@ static void rpc_system_system_device_info_process(const PB_Main* request, void*
     response->which_content = PB_Main_system_device_info_response_tag;
     response->which_content = PB_Main_system_device_info_response_tag;
     response->command_status = PB_CommandStatus_OK;
     response->command_status = PB_CommandStatus_OK;
 
 
-    RpcSystemSystemDeviceInfoContext device_info_context = {
+    RpcSystemContext device_info_context = {
         .session = session,
         .session = session,
         .response = response,
         .response = response,
     };
     };
@@ -202,6 +202,46 @@ static void rpc_system_system_protobuf_version_process(const PB_Main* request, v
     free(response);
     free(response);
 }
 }
 
 
+static void rpc_system_system_power_info_callback(
+    const char* key,
+    const char* value,
+    bool last,
+    void* context) {
+    furi_assert(key);
+    furi_assert(value);
+    RpcSystemContext* ctx = context;
+
+    char* str_key = strdup(key);
+    char* str_value = strdup(value);
+
+    ctx->response->has_next = !last;
+    ctx->response->content.system_device_info_response.key = str_key;
+    ctx->response->content.system_device_info_response.value = str_value;
+
+    rpc_send_and_release(ctx->session, ctx->response);
+}
+
+static void rpc_system_system_get_power_info_process(const PB_Main* request, void* context) {
+    furi_assert(request);
+    furi_assert(request->which_content == PB_Main_system_power_info_request_tag);
+
+    RpcSession* session = (RpcSession*)context;
+    furi_assert(session);
+
+    PB_Main* response = malloc(sizeof(PB_Main));
+    response->command_id = request->command_id;
+    response->which_content = PB_Main_system_power_info_response_tag;
+    response->command_status = PB_CommandStatus_OK;
+
+    RpcSystemContext power_info_context = {
+        .session = session,
+        .response = response,
+    };
+    furi_hal_power_info_get(rpc_system_system_power_info_callback, &power_info_context);
+
+    free(response);
+}
+
 void* rpc_system_system_alloc(RpcSession* session) {
 void* rpc_system_system_alloc(RpcSession* session) {
     RpcHandler rpc_handler = {
     RpcHandler rpc_handler = {
         .message_handler = NULL,
         .message_handler = NULL,
@@ -233,5 +273,8 @@ void* rpc_system_system_alloc(RpcSession* session) {
     rpc_handler.message_handler = rpc_system_system_protobuf_version_process;
     rpc_handler.message_handler = rpc_system_system_protobuf_version_process;
     rpc_add_handler(session, PB_Main_system_protobuf_version_request_tag, &rpc_handler);
     rpc_add_handler(session, PB_Main_system_protobuf_version_request_tag, &rpc_handler);
 
 
+    rpc_handler.message_handler = rpc_system_system_get_power_info_process;
+    rpc_add_handler(session, PB_Main_system_power_info_request_tag, &rpc_handler);
+
     return NULL;
     return NULL;
 }
 }

+ 4 - 2
applications/subghz/scenes/subghz_scene_save_name.c

@@ -42,8 +42,10 @@ void subghz_scene_save_name_on_enter(void* context) {
         SUBGHZ_MAX_LEN_NAME + 1, // buffer size
         SUBGHZ_MAX_LEN_NAME + 1, // buffer size
         dev_name_empty);
         dev_name_empty);
 
 
-    ValidatorIsFile* validator_is_file =
-        validator_is_file_alloc_init(SUBGHZ_APP_FOLDER, SUBGHZ_APP_EXTENSION);
+    ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
+        SUBGHZ_APP_FOLDER,
+        SUBGHZ_APP_EXTENSION,
+        (dev_name_empty) ? (NULL) : (subghz->file_name_tmp));
     text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
     text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
 
 
     view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdTextInput);
     view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdTextInput);

+ 7 - 5
applications/subghz/subghz_i.c

@@ -400,12 +400,14 @@ bool subghz_rename_file(SubGhz* subghz) {
     string_init_printf(
     string_init_printf(
         new_path, "%s/%s%s", SUBGHZ_APP_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION);
         new_path, "%s/%s%s", SUBGHZ_APP_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION);
 
 
-    FS_Error fs_result =
-        storage_common_rename(storage, string_get_cstr(old_path), string_get_cstr(new_path));
+    if(string_cmp(old_path, new_path) != 0) {
+        FS_Error fs_result =
+            storage_common_rename(storage, string_get_cstr(old_path), string_get_cstr(new_path));
 
 
-    if(fs_result != FSE_OK) {
-        dialog_message_show_storage_error(subghz->dialogs, "Cannot rename\n file/directory");
-        ret = false;
+        if(fs_result != FSE_OK) {
+            dialog_message_show_storage_error(subghz->dialogs, "Cannot rename\n file/directory");
+            ret = false;
+        }
     }
     }
 
 
     string_clear(old_path);
     string_clear(old_path);

+ 23 - 3
assets/compiled/flipper.pb.h

@@ -98,6 +98,11 @@ typedef struct _PB_Main {
         PB_System_PlayAudiovisualAlertRequest system_play_audiovisual_alert_request;
         PB_System_PlayAudiovisualAlertRequest system_play_audiovisual_alert_request;
         PB_System_ProtobufVersionRequest system_protobuf_version_request;
         PB_System_ProtobufVersionRequest system_protobuf_version_request;
         PB_System_ProtobufVersionResponse system_protobuf_version_response;
         PB_System_ProtobufVersionResponse system_protobuf_version_response;
+        PB_System_UpdateRequest system_update_request;
+        PB_Storage_BackupCreateRequest storage_backup_create_request;
+        PB_Storage_BackupRestoreRequest storage_backup_restore_request;
+        PB_System_PowerInfoRequest system_power_info_request;
+        PB_System_PowerInfoResponse system_power_info_response;
     } content; 
     } content; 
 } PB_Main;
 } PB_Main;
 
 
@@ -161,6 +166,11 @@ extern "C" {
 #define PB_Main_system_play_audiovisual_alert_request_tag 38
 #define PB_Main_system_play_audiovisual_alert_request_tag 38
 #define PB_Main_system_protobuf_version_request_tag 39
 #define PB_Main_system_protobuf_version_request_tag 39
 #define PB_Main_system_protobuf_version_response_tag 40
 #define PB_Main_system_protobuf_version_response_tag 40
+#define PB_Main_system_update_request_tag        41
+#define PB_Main_storage_backup_create_request_tag 42
+#define PB_Main_storage_backup_restore_request_tag 43
+#define PB_Main_system_power_info_request_tag    44
+#define PB_Main_system_power_info_response_tag   45
 
 
 /* Struct field encoding specification for nanopb */
 /* Struct field encoding specification for nanopb */
 #define PB_Empty_FIELDLIST(X, a) \
 #define PB_Empty_FIELDLIST(X, a) \
@@ -213,7 +223,12 @@ X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_get_datetime_response,content
 X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_set_datetime_request,content.system_set_datetime_request),  37) \
 X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_set_datetime_request,content.system_set_datetime_request),  37) \
 X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_play_audiovisual_alert_request,content.system_play_audiovisual_alert_request),  38) \
 X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_play_audiovisual_alert_request,content.system_play_audiovisual_alert_request),  38) \
 X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_protobuf_version_request,content.system_protobuf_version_request),  39) \
 X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_protobuf_version_request,content.system_protobuf_version_request),  39) \
-X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_protobuf_version_response,content.system_protobuf_version_response),  40)
+X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_protobuf_version_response,content.system_protobuf_version_response),  40) \
+X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_update_request,content.system_update_request),  41) \
+X(a, STATIC,   ONEOF,    MSG_W_CB, (content,storage_backup_create_request,content.storage_backup_create_request),  42) \
+X(a, STATIC,   ONEOF,    MSG_W_CB, (content,storage_backup_restore_request,content.storage_backup_restore_request),  43) \
+X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_power_info_request,content.system_power_info_request),  44) \
+X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_power_info_response,content.system_power_info_response),  45)
 #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
@@ -253,6 +268,11 @@ X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_protobuf_version_response,con
 #define PB_Main_content_system_play_audiovisual_alert_request_MSGTYPE PB_System_PlayAudiovisualAlertRequest
 #define PB_Main_content_system_play_audiovisual_alert_request_MSGTYPE PB_System_PlayAudiovisualAlertRequest
 #define PB_Main_content_system_protobuf_version_request_MSGTYPE PB_System_ProtobufVersionRequest
 #define PB_Main_content_system_protobuf_version_request_MSGTYPE PB_System_ProtobufVersionRequest
 #define PB_Main_content_system_protobuf_version_response_MSGTYPE PB_System_ProtobufVersionResponse
 #define PB_Main_content_system_protobuf_version_response_MSGTYPE PB_System_ProtobufVersionResponse
+#define PB_Main_content_system_update_request_MSGTYPE PB_System_UpdateRequest
+#define PB_Main_content_storage_backup_create_request_MSGTYPE PB_Storage_BackupCreateRequest
+#define PB_Main_content_storage_backup_restore_request_MSGTYPE PB_Storage_BackupRestoreRequest
+#define PB_Main_content_system_power_info_request_MSGTYPE PB_System_PowerInfoRequest
+#define PB_Main_content_system_power_info_response_MSGTYPE PB_System_PowerInfoResponse
 
 
 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;
@@ -266,9 +286,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_System_PingRequest_size) && defined(PB_System_PingResponse_size) && 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_ScreenFrame_size) && defined(PB_Storage_StatRequest_size) && defined(PB_Storage_StatResponse_size) && defined(PB_Gui_StartVirtualDisplayRequest_size) && defined(PB_Storage_InfoRequest_size) && defined(PB_Storage_RenameRequest_size) && defined(PB_System_DeviceInfoResponse_size)
+#if defined(PB_System_PingRequest_size) && defined(PB_System_PingResponse_size) && 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_ScreenFrame_size) && defined(PB_Storage_StatRequest_size) && defined(PB_Storage_StatResponse_size) && defined(PB_Gui_StartVirtualDisplayRequest_size) && defined(PB_Storage_InfoRequest_size) && defined(PB_Storage_RenameRequest_size) && defined(PB_System_DeviceInfoResponse_size) && defined(PB_System_UpdateRequest_size) && defined(PB_Storage_BackupCreateRequest_size) && defined(PB_Storage_BackupRestoreRequest_size) && defined(PB_System_PowerInfoResponse_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 f5[(6 + PB_System_PingRequest_size)]; char f6[(6 + PB_System_PingResponse_size)]; 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_ScreenFrame_size)]; char f24[(7 + PB_Storage_StatRequest_size)]; char f25[(7 + PB_Storage_StatResponse_size)]; char f26[(7 + PB_Gui_StartVirtualDisplayRequest_size)]; char f28[(7 + PB_Storage_InfoRequest_size)]; char f30[(7 + PB_Storage_RenameRequest_size)]; char f33[(7 + PB_System_DeviceInfoResponse_size)]; char f0[36];};
+union PB_Main_content_size_union {char f5[(6 + PB_System_PingRequest_size)]; char f6[(6 + PB_System_PingResponse_size)]; 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_ScreenFrame_size)]; char f24[(7 + PB_Storage_StatRequest_size)]; char f25[(7 + PB_Storage_StatResponse_size)]; char f26[(7 + PB_Gui_StartVirtualDisplayRequest_size)]; char f28[(7 + PB_Storage_InfoRequest_size)]; char f30[(7 + PB_Storage_RenameRequest_size)]; char f33[(7 + PB_System_DeviceInfoResponse_size)]; char f41[(7 + PB_System_UpdateRequest_size)]; char f42[(7 + PB_Storage_BackupCreateRequest_size)]; char f43[(7 + PB_Storage_BackupRestoreRequest_size)]; char f45[(7 + PB_System_PowerInfoResponse_size)]; char f0[36];};
 #endif
 #endif
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus

+ 1 - 1
assets/compiled/protobuf_version.h

@@ -1,3 +1,3 @@
 #pragma once
 #pragma once
 #define PROTOBUF_MAJOR_VERSION 0
 #define PROTOBUF_MAJOR_VERSION 0
-#define PROTOBUF_MINOR_VERSION 3
+#define PROTOBUF_MINOR_VERSION 5

+ 6 - 0
assets/compiled/storage.pb.c

@@ -51,5 +51,11 @@ PB_BIND(PB_Storage_Md5sumResponse, PB_Storage_Md5sumResponse, AUTO)
 PB_BIND(PB_Storage_RenameRequest, PB_Storage_RenameRequest, AUTO)
 PB_BIND(PB_Storage_RenameRequest, PB_Storage_RenameRequest, AUTO)
 
 
 
 
+PB_BIND(PB_Storage_BackupCreateRequest, PB_Storage_BackupCreateRequest, AUTO)
+
+
+PB_BIND(PB_Storage_BackupRestoreRequest, PB_Storage_BackupRestoreRequest, AUTO)
+
+
 
 
 
 

+ 30 - 0
assets/compiled/storage.pb.h

@@ -16,6 +16,14 @@ typedef enum _PB_Storage_File_FileType {
 } PB_Storage_File_FileType;
 } PB_Storage_File_FileType;
 
 
 /* Struct definitions */
 /* Struct definitions */
+typedef struct _PB_Storage_BackupCreateRequest { 
+    char *archive_path; 
+} PB_Storage_BackupCreateRequest;
+
+typedef struct _PB_Storage_BackupRestoreRequest { 
+    char *archive_path; 
+} PB_Storage_BackupRestoreRequest;
+
 typedef struct _PB_Storage_InfoRequest { 
 typedef struct _PB_Storage_InfoRequest { 
     char *path; 
     char *path; 
 } PB_Storage_InfoRequest;
 } PB_Storage_InfoRequest;
@@ -114,6 +122,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_RenameRequest_init_default    {NULL, NULL}
 #define PB_Storage_RenameRequest_init_default    {NULL, NULL}
+#define PB_Storage_BackupCreateRequest_init_default {NULL}
+#define PB_Storage_BackupRestoreRequest_init_default {NULL}
 #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_InfoRequest_init_zero         {NULL}
 #define PB_Storage_InfoRequest_init_zero         {NULL}
 #define PB_Storage_InfoResponse_init_zero        {0, 0}
 #define PB_Storage_InfoResponse_init_zero        {0, 0}
@@ -129,8 +139,12 @@ extern "C" {
 #define PB_Storage_Md5sumRequest_init_zero       {NULL}
 #define PB_Storage_Md5sumRequest_init_zero       {NULL}
 #define PB_Storage_Md5sumResponse_init_zero      {""}
 #define PB_Storage_Md5sumResponse_init_zero      {""}
 #define PB_Storage_RenameRequest_init_zero       {NULL, NULL}
 #define PB_Storage_RenameRequest_init_zero       {NULL, NULL}
+#define PB_Storage_BackupCreateRequest_init_zero {NULL}
+#define PB_Storage_BackupRestoreRequest_init_zero {NULL}
 
 
 /* Field tags (for use in manual encoding/decoding) */
 /* Field tags (for use in manual encoding/decoding) */
+#define PB_Storage_BackupCreateRequest_archive_path_tag 1
+#define PB_Storage_BackupRestoreRequest_archive_path_tag 1
 #define PB_Storage_InfoRequest_path_tag          1
 #define PB_Storage_InfoRequest_path_tag          1
 #define PB_Storage_ListRequest_path_tag          1
 #define PB_Storage_ListRequest_path_tag          1
 #define PB_Storage_Md5sumRequest_path_tag        1
 #define PB_Storage_Md5sumRequest_path_tag        1
@@ -241,6 +255,16 @@ X(a, POINTER,  SINGULAR, STRING,   new_path,          2)
 #define PB_Storage_RenameRequest_CALLBACK NULL
 #define PB_Storage_RenameRequest_CALLBACK NULL
 #define PB_Storage_RenameRequest_DEFAULT NULL
 #define PB_Storage_RenameRequest_DEFAULT NULL
 
 
+#define PB_Storage_BackupCreateRequest_FIELDLIST(X, a) \
+X(a, POINTER,  SINGULAR, STRING,   archive_path,      1)
+#define PB_Storage_BackupCreateRequest_CALLBACK NULL
+#define PB_Storage_BackupCreateRequest_DEFAULT NULL
+
+#define PB_Storage_BackupRestoreRequest_FIELDLIST(X, a) \
+X(a, POINTER,  SINGULAR, STRING,   archive_path,      1)
+#define PB_Storage_BackupRestoreRequest_CALLBACK NULL
+#define PB_Storage_BackupRestoreRequest_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_InfoRequest_msg;
 extern const pb_msgdesc_t PB_Storage_InfoRequest_msg;
 extern const pb_msgdesc_t PB_Storage_InfoResponse_msg;
 extern const pb_msgdesc_t PB_Storage_InfoResponse_msg;
@@ -256,6 +280,8 @@ extern const pb_msgdesc_t PB_Storage_MkdirRequest_msg;
 extern const pb_msgdesc_t PB_Storage_Md5sumRequest_msg;
 extern const pb_msgdesc_t PB_Storage_Md5sumRequest_msg;
 extern const pb_msgdesc_t PB_Storage_Md5sumResponse_msg;
 extern const pb_msgdesc_t PB_Storage_Md5sumResponse_msg;
 extern const pb_msgdesc_t PB_Storage_RenameRequest_msg;
 extern const pb_msgdesc_t PB_Storage_RenameRequest_msg;
+extern const pb_msgdesc_t PB_Storage_BackupCreateRequest_msg;
+extern const pb_msgdesc_t PB_Storage_BackupRestoreRequest_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
@@ -273,6 +299,8 @@ extern const pb_msgdesc_t PB_Storage_RenameRequest_msg;
 #define PB_Storage_Md5sumRequest_fields &PB_Storage_Md5sumRequest_msg
 #define PB_Storage_Md5sumRequest_fields &PB_Storage_Md5sumRequest_msg
 #define PB_Storage_Md5sumResponse_fields &PB_Storage_Md5sumResponse_msg
 #define PB_Storage_Md5sumResponse_fields &PB_Storage_Md5sumResponse_msg
 #define PB_Storage_RenameRequest_fields &PB_Storage_RenameRequest_msg
 #define PB_Storage_RenameRequest_fields &PB_Storage_RenameRequest_msg
+#define PB_Storage_BackupCreateRequest_fields &PB_Storage_BackupCreateRequest_msg
+#define PB_Storage_BackupRestoreRequest_fields &PB_Storage_BackupRestoreRequest_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 */
@@ -288,6 +316,8 @@ extern const pb_msgdesc_t PB_Storage_RenameRequest_msg;
 /* PB_Storage_MkdirRequest_size depends on runtime parameters */
 /* PB_Storage_MkdirRequest_size depends on runtime parameters */
 /* PB_Storage_Md5sumRequest_size depends on runtime parameters */
 /* PB_Storage_Md5sumRequest_size depends on runtime parameters */
 /* PB_Storage_RenameRequest_size depends on runtime parameters */
 /* PB_Storage_RenameRequest_size depends on runtime parameters */
+/* PB_Storage_BackupCreateRequest_size depends on runtime parameters */
+/* PB_Storage_BackupRestoreRequest_size depends on runtime parameters */
 #define PB_Storage_InfoResponse_size             22
 #define PB_Storage_InfoResponse_size             22
 #define PB_Storage_Md5sumResponse_size           34
 #define PB_Storage_Md5sumResponse_size           34
 
 

+ 9 - 0
assets/compiled/system.pb.c

@@ -45,5 +45,14 @@ PB_BIND(PB_System_ProtobufVersionRequest, PB_System_ProtobufVersionRequest, AUTO
 PB_BIND(PB_System_ProtobufVersionResponse, PB_System_ProtobufVersionResponse, AUTO)
 PB_BIND(PB_System_ProtobufVersionResponse, PB_System_ProtobufVersionResponse, AUTO)
 
 
 
 
+PB_BIND(PB_System_UpdateRequest, PB_System_UpdateRequest, AUTO)
+
+
+PB_BIND(PB_System_PowerInfoRequest, PB_System_PowerInfoRequest, AUTO)
+
+
+PB_BIND(PB_System_PowerInfoResponse, PB_System_PowerInfoResponse, AUTO)
+
+
 
 
 
 

+ 47 - 0
assets/compiled/system.pb.h

@@ -45,10 +45,23 @@ typedef struct _PB_System_PlayAudiovisualAlertRequest {
     char dummy_field;
     char dummy_field;
 } PB_System_PlayAudiovisualAlertRequest;
 } PB_System_PlayAudiovisualAlertRequest;
 
 
+typedef struct _PB_System_PowerInfoRequest { 
+    char dummy_field;
+} PB_System_PowerInfoRequest;
+
+typedef struct _PB_System_PowerInfoResponse { 
+    char *key; 
+    char *value; 
+} PB_System_PowerInfoResponse;
+
 typedef struct _PB_System_ProtobufVersionRequest { 
 typedef struct _PB_System_ProtobufVersionRequest { 
     char dummy_field;
     char dummy_field;
 } PB_System_ProtobufVersionRequest;
 } PB_System_ProtobufVersionRequest;
 
 
+typedef struct _PB_System_UpdateRequest { 
+    char *update_folder; 
+} PB_System_UpdateRequest;
+
 typedef struct _PB_System_DateTime { 
 typedef struct _PB_System_DateTime { 
     /* Time */
     /* Time */
     uint8_t hour; /* *< Hour in 24H format: 0-23 */
     uint8_t hour; /* *< Hour in 24H format: 0-23 */
@@ -105,6 +118,9 @@ extern "C" {
 #define PB_System_PlayAudiovisualAlertRequest_init_default {0}
 #define PB_System_PlayAudiovisualAlertRequest_init_default {0}
 #define PB_System_ProtobufVersionRequest_init_default {0}
 #define PB_System_ProtobufVersionRequest_init_default {0}
 #define PB_System_ProtobufVersionResponse_init_default {0, 0}
 #define PB_System_ProtobufVersionResponse_init_default {0, 0}
+#define PB_System_UpdateRequest_init_default     {NULL}
+#define PB_System_PowerInfoRequest_init_default  {0}
+#define PB_System_PowerInfoResponse_init_default {NULL, NULL}
 #define PB_System_PingRequest_init_zero          {NULL}
 #define PB_System_PingRequest_init_zero          {NULL}
 #define PB_System_PingResponse_init_zero         {NULL}
 #define PB_System_PingResponse_init_zero         {NULL}
 #define PB_System_RebootRequest_init_zero        {_PB_System_RebootRequest_RebootMode_MIN}
 #define PB_System_RebootRequest_init_zero        {_PB_System_RebootRequest_RebootMode_MIN}
@@ -118,12 +134,18 @@ extern "C" {
 #define PB_System_PlayAudiovisualAlertRequest_init_zero {0}
 #define PB_System_PlayAudiovisualAlertRequest_init_zero {0}
 #define PB_System_ProtobufVersionRequest_init_zero {0}
 #define PB_System_ProtobufVersionRequest_init_zero {0}
 #define PB_System_ProtobufVersionResponse_init_zero {0, 0}
 #define PB_System_ProtobufVersionResponse_init_zero {0, 0}
+#define PB_System_UpdateRequest_init_zero        {NULL}
+#define PB_System_PowerInfoRequest_init_zero     {0}
+#define PB_System_PowerInfoResponse_init_zero    {NULL, NULL}
 
 
 /* Field tags (for use in manual encoding/decoding) */
 /* Field tags (for use in manual encoding/decoding) */
 #define PB_System_DeviceInfoResponse_key_tag     1
 #define PB_System_DeviceInfoResponse_key_tag     1
 #define PB_System_DeviceInfoResponse_value_tag   2
 #define PB_System_DeviceInfoResponse_value_tag   2
 #define PB_System_PingRequest_data_tag           1
 #define PB_System_PingRequest_data_tag           1
 #define PB_System_PingResponse_data_tag          1
 #define PB_System_PingResponse_data_tag          1
+#define PB_System_PowerInfoResponse_key_tag      1
+#define PB_System_PowerInfoResponse_value_tag    2
+#define PB_System_UpdateRequest_update_folder_tag 1
 #define PB_System_DateTime_hour_tag              1
 #define PB_System_DateTime_hour_tag              1
 #define PB_System_DateTime_minute_tag            2
 #define PB_System_DateTime_minute_tag            2
 #define PB_System_DateTime_second_tag            3
 #define PB_System_DateTime_second_tag            3
@@ -213,6 +235,22 @@ X(a, STATIC,   SINGULAR, UINT32,   minor,             2)
 #define PB_System_ProtobufVersionResponse_CALLBACK NULL
 #define PB_System_ProtobufVersionResponse_CALLBACK NULL
 #define PB_System_ProtobufVersionResponse_DEFAULT NULL
 #define PB_System_ProtobufVersionResponse_DEFAULT NULL
 
 
+#define PB_System_UpdateRequest_FIELDLIST(X, a) \
+X(a, POINTER,  SINGULAR, STRING,   update_folder,     1)
+#define PB_System_UpdateRequest_CALLBACK NULL
+#define PB_System_UpdateRequest_DEFAULT NULL
+
+#define PB_System_PowerInfoRequest_FIELDLIST(X, a) \
+
+#define PB_System_PowerInfoRequest_CALLBACK NULL
+#define PB_System_PowerInfoRequest_DEFAULT NULL
+
+#define PB_System_PowerInfoResponse_FIELDLIST(X, a) \
+X(a, POINTER,  SINGULAR, STRING,   key,               1) \
+X(a, POINTER,  SINGULAR, STRING,   value,             2)
+#define PB_System_PowerInfoResponse_CALLBACK NULL
+#define PB_System_PowerInfoResponse_DEFAULT NULL
+
 extern const pb_msgdesc_t PB_System_PingRequest_msg;
 extern const pb_msgdesc_t PB_System_PingRequest_msg;
 extern const pb_msgdesc_t PB_System_PingResponse_msg;
 extern const pb_msgdesc_t PB_System_PingResponse_msg;
 extern const pb_msgdesc_t PB_System_RebootRequest_msg;
 extern const pb_msgdesc_t PB_System_RebootRequest_msg;
@@ -226,6 +264,9 @@ extern const pb_msgdesc_t PB_System_DateTime_msg;
 extern const pb_msgdesc_t PB_System_PlayAudiovisualAlertRequest_msg;
 extern const pb_msgdesc_t PB_System_PlayAudiovisualAlertRequest_msg;
 extern const pb_msgdesc_t PB_System_ProtobufVersionRequest_msg;
 extern const pb_msgdesc_t PB_System_ProtobufVersionRequest_msg;
 extern const pb_msgdesc_t PB_System_ProtobufVersionResponse_msg;
 extern const pb_msgdesc_t PB_System_ProtobufVersionResponse_msg;
+extern const pb_msgdesc_t PB_System_UpdateRequest_msg;
+extern const pb_msgdesc_t PB_System_PowerInfoRequest_msg;
+extern const pb_msgdesc_t PB_System_PowerInfoResponse_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_System_PingRequest_fields &PB_System_PingRequest_msg
 #define PB_System_PingRequest_fields &PB_System_PingRequest_msg
@@ -241,17 +282,23 @@ extern const pb_msgdesc_t PB_System_ProtobufVersionResponse_msg;
 #define PB_System_PlayAudiovisualAlertRequest_fields &PB_System_PlayAudiovisualAlertRequest_msg
 #define PB_System_PlayAudiovisualAlertRequest_fields &PB_System_PlayAudiovisualAlertRequest_msg
 #define PB_System_ProtobufVersionRequest_fields &PB_System_ProtobufVersionRequest_msg
 #define PB_System_ProtobufVersionRequest_fields &PB_System_ProtobufVersionRequest_msg
 #define PB_System_ProtobufVersionResponse_fields &PB_System_ProtobufVersionResponse_msg
 #define PB_System_ProtobufVersionResponse_fields &PB_System_ProtobufVersionResponse_msg
+#define PB_System_UpdateRequest_fields &PB_System_UpdateRequest_msg
+#define PB_System_PowerInfoRequest_fields &PB_System_PowerInfoRequest_msg
+#define PB_System_PowerInfoResponse_fields &PB_System_PowerInfoResponse_msg
 
 
 /* Maximum encoded size of messages (where known) */
 /* Maximum encoded size of messages (where known) */
 /* PB_System_PingRequest_size depends on runtime parameters */
 /* PB_System_PingRequest_size depends on runtime parameters */
 /* PB_System_PingResponse_size depends on runtime parameters */
 /* PB_System_PingResponse_size depends on runtime parameters */
 /* PB_System_DeviceInfoResponse_size depends on runtime parameters */
 /* PB_System_DeviceInfoResponse_size depends on runtime parameters */
+/* PB_System_UpdateRequest_size depends on runtime parameters */
+/* PB_System_PowerInfoResponse_size depends on runtime parameters */
 #define PB_System_DateTime_size                  22
 #define PB_System_DateTime_size                  22
 #define PB_System_DeviceInfoRequest_size         0
 #define PB_System_DeviceInfoRequest_size         0
 #define PB_System_FactoryResetRequest_size       0
 #define PB_System_FactoryResetRequest_size       0
 #define PB_System_GetDateTimeRequest_size        0
 #define PB_System_GetDateTimeRequest_size        0
 #define PB_System_GetDateTimeResponse_size       24
 #define PB_System_GetDateTimeResponse_size       24
 #define PB_System_PlayAudiovisualAlertRequest_size 0
 #define PB_System_PlayAudiovisualAlertRequest_size 0
+#define PB_System_PowerInfoRequest_size          0
 #define PB_System_ProtobufVersionRequest_size    0
 #define PB_System_ProtobufVersionRequest_size    0
 #define PB_System_ProtobufVersionResponse_size   12
 #define PB_System_ProtobufVersionResponse_size   12
 #define PB_System_RebootRequest_size             2
 #define PB_System_RebootRequest_size             2

+ 1 - 1
assets/protobuf

@@ -1 +1 @@
-Subproject commit cd11b029ac21462ea8a7615126d0a29e087c2908
+Subproject commit 0403ae1ba7a4501274da54b3aa6274f76fdd090c

+ 38 - 20
firmware/targets/f7/furi_hal/furi_hal_crypto.c

@@ -15,13 +15,16 @@
 #define CRYPTO_TIMEOUT (1000)
 #define CRYPTO_TIMEOUT (1000)
 
 
 #define CRYPTO_MODE_ENCRYPT 0U
 #define CRYPTO_MODE_ENCRYPT 0U
+#define CRYPTO_MODE_INIT (AES_CR_MODE_0)
 #define CRYPTO_MODE_DECRYPT (AES_CR_MODE_1)
 #define CRYPTO_MODE_DECRYPT (AES_CR_MODE_1)
 #define CRYPTO_MODE_DECRYPT_INIT (AES_CR_MODE_0 | AES_CR_MODE_1)
 #define CRYPTO_MODE_DECRYPT_INIT (AES_CR_MODE_0 | AES_CR_MODE_1)
+
 #define CRYPTO_DATATYPE_32B 0U
 #define CRYPTO_DATATYPE_32B 0U
 #define CRYPTO_KEYSIZE_256B (AES_CR_KEYSIZE)
 #define CRYPTO_KEYSIZE_256B (AES_CR_KEYSIZE)
 #define CRYPTO_AES_CBC (AES_CR_CHMOD_0)
 #define CRYPTO_AES_CBC (AES_CR_CHMOD_0)
 
 
 static osMutexId_t furi_hal_crypto_mutex = NULL;
 static osMutexId_t furi_hal_crypto_mutex = NULL;
+static bool furi_hal_crypto_mode_init_done = false;
 
 
 static const uint8_t enclave_signature_iv[ENCLAVE_FACTORY_KEY_SLOTS][16] = {
 static const uint8_t enclave_signature_iv[ENCLAVE_FACTORY_KEY_SLOTS][16] = {
     {0xac, 0x5d, 0x68, 0xb8, 0x79, 0x74, 0xfc, 0x7f, 0x45, 0x02, 0x82, 0xf1, 0x48, 0x7e, 0x75, 0x8a},
     {0xac, 0x5d, 0x68, 0xb8, 0x79, 0x74, 0xfc, 0x7f, 0x45, 0x02, 0x82, 0xf1, 0x48, 0x7e, 0x75, 0x8a},
@@ -177,20 +180,8 @@ bool furi_hal_crypto_store_add_key(FuriHalCryptoKey* key, uint8_t* slot) {
     return (shci_state == SHCI_Success);
     return (shci_state == SHCI_Success);
 }
 }
 
 
-static void crypto_enable() {
-    SET_BIT(AES1->CR, AES_CR_EN);
-}
-
-static void crypto_disable() {
-    CLEAR_BIT(AES1->CR, AES_CR_EN);
-    FURI_CRITICAL_ENTER();
-    LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_AES1);
-    LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_AES1);
-    FURI_CRITICAL_EXIT();
-}
-
 static void crypto_key_init(uint32_t* key, uint32_t* iv) {
 static void crypto_key_init(uint32_t* key, uint32_t* iv) {
-    crypto_disable();
+    CLEAR_BIT(AES1->CR, AES_CR_EN);
     MODIFY_REG(
     MODIFY_REG(
         AES1->CR,
         AES1->CR,
         AES_CR_DATATYPE | AES_CR_KEYSIZE | AES_CR_CHMOD,
         AES_CR_DATATYPE | AES_CR_KEYSIZE | AES_CR_CHMOD,
@@ -254,12 +245,13 @@ bool furi_hal_crypto_store_load_key(uint8_t slot, const uint8_t* iv) {
         return false;
         return false;
     }
     }
 
 
+    furi_hal_crypto_mode_init_done = false;
     crypto_key_init(NULL, (uint32_t*)iv);
     crypto_key_init(NULL, (uint32_t*)iv);
 
 
     if(SHCI_C2_FUS_LoadUsrKey(slot) == SHCI_Success) {
     if(SHCI_C2_FUS_LoadUsrKey(slot) == SHCI_Success) {
         return true;
         return true;
     } else {
     } else {
-        crypto_disable();
+        CLEAR_BIT(AES1->CR, AES_CR_EN);
         furi_check(osMutexRelease(furi_hal_crypto_mutex) == osOK);
         furi_check(osMutexRelease(furi_hal_crypto_mutex) == osOK);
         return false;
         return false;
     }
     }
@@ -270,9 +262,16 @@ bool furi_hal_crypto_store_unload_key(uint8_t slot) {
         return false;
         return false;
     }
     }
 
 
-    crypto_disable();
+    CLEAR_BIT(AES1->CR, AES_CR_EN);
 
 
     SHCI_CmdStatus_t shci_state = SHCI_C2_FUS_UnloadUsrKey(slot);
     SHCI_CmdStatus_t shci_state = SHCI_C2_FUS_UnloadUsrKey(slot);
+    furi_assert(shci_state == SHCI_Success);
+
+    FURI_CRITICAL_ENTER();
+    LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_AES1);
+    LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_AES1);
+    FURI_CRITICAL_EXIT();
+
     furi_check(osMutexRelease(furi_hal_crypto_mutex) == osOK);
     furi_check(osMutexRelease(furi_hal_crypto_mutex) == osOK);
     return (shci_state == SHCI_Success);
     return (shci_state == SHCI_Success);
 }
 }
@@ -280,7 +279,7 @@ bool furi_hal_crypto_store_unload_key(uint8_t slot) {
 bool furi_hal_crypto_encrypt(const uint8_t* input, uint8_t* output, size_t size) {
 bool furi_hal_crypto_encrypt(const uint8_t* input, uint8_t* output, size_t size) {
     bool state = false;
     bool state = false;
 
 
-    crypto_enable();
+    SET_BIT(AES1->CR, AES_CR_EN);
 
 
     MODIFY_REG(AES1->CR, AES_CR_MODE, CRYPTO_MODE_ENCRYPT);
     MODIFY_REG(AES1->CR, AES_CR_MODE, CRYPTO_MODE_ENCRYPT);
 
 
@@ -295,7 +294,7 @@ bool furi_hal_crypto_encrypt(const uint8_t* input, uint8_t* output, size_t size)
         }
         }
     }
     }
 
 
-    crypto_disable();
+    CLEAR_BIT(AES1->CR, AES_CR_EN);
 
 
     return state;
     return state;
 }
 }
@@ -303,9 +302,28 @@ bool furi_hal_crypto_encrypt(const uint8_t* input, uint8_t* output, size_t size)
 bool furi_hal_crypto_decrypt(const uint8_t* input, uint8_t* output, size_t size) {
 bool furi_hal_crypto_decrypt(const uint8_t* input, uint8_t* output, size_t size) {
     bool state = false;
     bool state = false;
 
 
-    MODIFY_REG(AES1->CR, AES_CR_MODE, CRYPTO_MODE_DECRYPT_INIT);
+    if(!furi_hal_crypto_mode_init_done) {
+        MODIFY_REG(AES1->CR, AES_CR_MODE, CRYPTO_MODE_INIT);
 
 
-    crypto_enable();
+        SET_BIT(AES1->CR, AES_CR_EN);
+
+        uint32_t countdown = CRYPTO_TIMEOUT;
+        while(!READ_BIT(AES1->SR, AES_SR_CCF)) {
+            if(LL_SYSTICK_IsActiveCounterFlag()) {
+                countdown--;
+            }
+            if(countdown == 0) {
+                return false;
+            }
+        }
+
+        SET_BIT(AES1->CR, AES_CR_CCFC);
+
+        furi_hal_crypto_mode_init_done = true;
+    }
+
+    MODIFY_REG(AES1->CR, AES_CR_MODE, CRYPTO_MODE_DECRYPT);
+    SET_BIT(AES1->CR, AES_CR_EN);
 
 
     for(size_t i = 0; i < size; i += CRYPTO_BLK_LEN) {
     for(size_t i = 0; i < size; i += CRYPTO_BLK_LEN) {
         size_t blk_len = size - i;
         size_t blk_len = size - i;
@@ -318,7 +336,7 @@ bool furi_hal_crypto_decrypt(const uint8_t* input, uint8_t* output, size_t size)
         }
         }
     }
     }
 
 
-    crypto_disable();
+    CLEAR_BIT(AES1->CR, AES_CR_EN);
 
 
     return state;
     return state;
 }
 }

+ 62 - 0
firmware/targets/f7/furi_hal/furi_hal_power.c

@@ -239,6 +239,13 @@ uint32_t furi_hal_power_get_battery_full_capacity() {
     return ret;
     return ret;
 }
 }
 
 
+uint32_t furi_hal_power_get_battery_design_capacity() {
+    furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
+    uint32_t ret = bq27220_get_design_capacity(&furi_hal_i2c_handle_power);
+    furi_hal_i2c_release(&furi_hal_i2c_handle_power);
+    return ret;
+}
+
 float furi_hal_power_get_battery_voltage(FuriHalPowerIC ic) {
 float furi_hal_power_get_battery_voltage(FuriHalPowerIC ic) {
     float ret = 0.0f;
     float ret = 0.0f;
 
 
@@ -399,3 +406,58 @@ void furi_hal_power_suppress_charge_exit() {
         furi_hal_i2c_release(&furi_hal_i2c_handle_power);
         furi_hal_i2c_release(&furi_hal_i2c_handle_power);
     }
     }
 }
 }
+
+void furi_hal_power_info_get(FuriHalPowerInfoCallback out, void* context) {
+    furi_assert(out);
+
+    string_t value;
+    string_init(value);
+
+    // Power Info version
+    out("power_info_major", "1", false, context);
+    out("power_info_minor", "0", false, context);
+
+    uint8_t charge = furi_hal_power_get_pct();
+
+    string_printf(value, "%u", charge);
+    out("charge_level", string_get_cstr(value), false, context);
+
+    if(furi_hal_power_is_charging()) {
+        if(charge < 100) {
+            string_printf(value, "charging");
+        } else {
+            string_printf(value, "charged");
+        }
+    } else {
+        string_printf(value, "discharging");
+    }
+    out("charge_state", string_get_cstr(value), false, context);
+
+    uint16_t voltage =
+        (uint16_t)(furi_hal_power_get_battery_voltage(FuriHalPowerICFuelGauge) * 1000.f);
+    string_printf(value, "%u", voltage);
+    out("battery_voltage", string_get_cstr(value), false, context);
+
+    int16_t current =
+        (int16_t)(furi_hal_power_get_battery_current(FuriHalPowerICFuelGauge) * 1000.f);
+    string_printf(value, "%d", current);
+    out("battery_current", string_get_cstr(value), false, context);
+
+    int16_t temperature = (int16_t)furi_hal_power_get_battery_temperature(FuriHalPowerICFuelGauge);
+    string_printf(value, "%d", temperature);
+    out("gauge_temp", string_get_cstr(value), false, context);
+
+    string_printf(value, "%u", furi_hal_power_get_bat_health_pct());
+    out("battery_health", string_get_cstr(value), false, context);
+
+    string_printf(value, "%u", furi_hal_power_get_battery_remaining_capacity());
+    out("capacity_remain", string_get_cstr(value), false, context);
+
+    string_printf(value, "%u", furi_hal_power_get_battery_full_capacity());
+    out("capacity_full", string_get_cstr(value), false, context);
+
+    string_printf(value, "%u", furi_hal_power_get_battery_design_capacity());
+    out("capacity_design", string_get_cstr(value), true, context);
+
+    string_clear(value);
+}

+ 16 - 5
firmware/targets/f7/furi_hal/furi_hal_speaker.c

@@ -25,21 +25,32 @@ void furi_hal_speaker_start(float frequency, float volume) {
     if(volume > 1) volume = 1;
     if(volume > 1) volume = 1;
     volume = volume * volume * volume;
     volume = volume * volume * volume;
 
 
+    uint32_t autoreload = (SystemCoreClock / FURI_HAL_SPEAKER_PRESCALER / frequency) - 1;
+    if(autoreload < 2) {
+        autoreload = 2;
+    } else if(autoreload > UINT16_MAX) {
+        autoreload = UINT16_MAX;
+    }
+
     LL_TIM_InitTypeDef TIM_InitStruct = {0};
     LL_TIM_InitTypeDef TIM_InitStruct = {0};
     TIM_InitStruct.Prescaler = FURI_HAL_SPEAKER_PRESCALER - 1;
     TIM_InitStruct.Prescaler = FURI_HAL_SPEAKER_PRESCALER - 1;
-    TIM_InitStruct.Autoreload = ((SystemCoreClock / FURI_HAL_SPEAKER_PRESCALER) / frequency) - 1;
+    TIM_InitStruct.Autoreload = autoreload;
     LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct);
     LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct);
 
 
 #ifdef FURI_HAL_SPEAKER_NEW_VOLUME
 #ifdef FURI_HAL_SPEAKER_NEW_VOLUME
-    uint16_t compare_value = volume * FURI_HAL_SPEAKER_MAX_VOLUME;
-    uint16_t clip_value = volume * TIM_InitStruct.Autoreload / 2;
+    uint32_t compare_value = volume * FURI_HAL_SPEAKER_MAX_VOLUME;
+    uint32_t clip_value = volume * TIM_InitStruct.Autoreload / 2;
     if(compare_value > clip_value) {
     if(compare_value > clip_value) {
         compare_value = clip_value;
         compare_value = clip_value;
     }
     }
 #else
 #else
-    uint16_t compare_value = volume * TIM_InitStruct.Autoreload / 2;
+    uint32_t compare_value = volume * autoreload / 2;
 #endif
 #endif
 
 
+    if(compare_value == 0) {
+        compare_value = 1;
+    }
+
     LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
     LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
     TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
     TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
     TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
     TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
@@ -51,6 +62,6 @@ void furi_hal_speaker_start(float frequency, float volume) {
 }
 }
 
 
 void furi_hal_speaker_stop() {
 void furi_hal_speaker_stop() {
-    LL_TIM_CC_DisableChannel(FURI_HAL_SPEAKER_TIMER, FURI_HAL_SPEAKER_CHANNEL);
+    LL_TIM_DisableAllOutputs(FURI_HAL_SPEAKER_TIMER);
     LL_TIM_DisableCounter(FURI_HAL_SPEAKER_TIMER);
     LL_TIM_DisableCounter(FURI_HAL_SPEAKER_TIMER);
 }
 }

+ 23 - 0
firmware/targets/furi_hal_include/furi_hal_power.h

@@ -113,6 +113,12 @@ uint32_t furi_hal_power_get_battery_remaining_capacity();
  */
  */
 uint32_t furi_hal_power_get_battery_full_capacity();
 uint32_t furi_hal_power_get_battery_full_capacity();
 
 
+/** Get battery capacity in mAh from battery profile
+ *
+ * @return     capacity in mAh
+ */
+uint32_t furi_hal_power_get_battery_design_capacity();
+
 /** Get battery voltage in V
 /** Get battery voltage in V
  *
  *
  * @param      ic    FuriHalPowerIc to get measurment
  * @param      ic    FuriHalPowerIc to get measurment
@@ -171,6 +177,23 @@ void furi_hal_power_suppress_charge_enter();
  */
  */
 void furi_hal_power_suppress_charge_exit();
 void furi_hal_power_suppress_charge_exit();
 
 
+/** Callback type called by furi_hal_power_info_get every time another key-value pair of information is ready
+ *
+ * @param      key[in]      power information type identifier
+ * @param      value[in]    power information value
+ * @param      last[in]     whether the passed key-value pair is the last one
+ * @param      context[in]  to pass to callback
+ */
+typedef void (
+    *FuriHalPowerInfoCallback)(const char* key, const char* value, bool last, void* context);
+
+/** Get power information
+ *
+ * @param[in]  callback     callback to provide with new data
+ * @param[in]  context      context to pass to callback
+ */
+void furi_hal_power_info_get(FuriHalPowerInfoCallback callback, void* context);
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif