[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>
This commit is contained in:
		| @@ -31,8 +31,8 @@ void archive_scene_rename_on_enter(void* context) { | ||||
|         MAX_TEXT_INPUT_LEN, | ||||
|         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); | ||||
|  | ||||
|     view_dispatcher_switch_to_view(archive->view_dispatcher, ArchiveViewTextInput); | ||||
|   | ||||
| @@ -5,11 +5,19 @@ | ||||
| struct ValidatorIsFile { | ||||
|     const char* app_path_folder; | ||||
|     const char* app_extension; | ||||
|     char* current_name; | ||||
| }; | ||||
|  | ||||
| bool validator_is_file_callback(const char* text, string_t error, void* context) { | ||||
|     furi_assert(context); | ||||
|     ValidatorIsFile* instance = context; | ||||
|  | ||||
|     if(instance->current_name != NULL) { | ||||
|         if(strcmp(instance->current_name, text) == 0) { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     bool ret = true; | ||||
|     string_t path; | ||||
|     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; | ||||
| } | ||||
|  | ||||
| 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)); | ||||
|  | ||||
|     instance->app_path_folder = app_path_folder; | ||||
|     instance->app_extension = app_extension; | ||||
|     instance->current_name = strdup(current_name); | ||||
|  | ||||
|     return instance; | ||||
| } | ||||
|  | ||||
| void validator_is_file_free(ValidatorIsFile* instance) { | ||||
|     furi_assert(instance); | ||||
|     free(instance->current_name); | ||||
|     free(instance); | ||||
| } | ||||
|   | ||||
| @@ -8,8 +8,10 @@ extern "C" { | ||||
| #endif | ||||
| 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); | ||||
|  | ||||
|   | ||||
| @@ -35,7 +35,7 @@ void iButtonSceneSaveName::on_enter(iButtonApp* app) { | ||||
|         key_name_empty); | ||||
|  | ||||
|     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); | ||||
|  | ||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewTextInput); | ||||
|   | ||||
| @@ -21,8 +21,8 @@ void InfraredAppSceneEditRename::on_enter(InfraredApp* app) { | ||||
|         enter_name_length = InfraredAppRemoteManager::max_remote_name_length; | ||||
|         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); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -22,7 +22,7 @@ void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool need_restore) { | ||||
|         key_name_empty); | ||||
|  | ||||
|     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); | ||||
|  | ||||
|     app->view_controller.switch_to<TextInputVM>(); | ||||
|   | ||||
| @@ -30,7 +30,7 @@ void nfc_scene_save_name_on_enter(void* context) { | ||||
|         dev_name_empty); | ||||
|  | ||||
|     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); | ||||
|  | ||||
|     view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput); | ||||
|   | ||||
| @@ -20,6 +20,14 @@ void power_cli_reboot2dfu(Cli* cli, string_t args) { | ||||
|     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) { | ||||
|     furi_hal_power_dump_state(); | ||||
| } | ||||
| @@ -52,6 +60,7 @@ static void power_cli_command_print_usage() { | ||||
|     printf("\toff\t - shutdown power\r\n"); | ||||
|     printf("\treboot\t - reboot\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("\t5v <0 or 1>\t - enable or disable 5v ext\r\n"); | ||||
|     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { | ||||
| @@ -84,6 +93,11 @@ void power_cli(Cli* cli, string_t args, void* context) { | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         if(string_cmp_str(cmd, "info") == 0) { | ||||
|             power_cli_info(cli, args); | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         if(string_cmp_str(cmd, "debug") == 0) { | ||||
|             power_cli_debug(cli, args); | ||||
|             break; | ||||
|   | ||||
| @@ -4,6 +4,8 @@ | ||||
| #include <furi_hal.h> | ||||
| #include <semphr.h> | ||||
|  | ||||
| #define TAG "RpcCli" | ||||
|  | ||||
| typedef struct { | ||||
|     Cli* cli; | ||||
|     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) { | ||||
|     Rpc* rpc = context; | ||||
|  | ||||
|     uint32_t mem_before = memmgr_get_free_heap(); | ||||
|     FURI_LOG_D(TAG, "Free memory %d", mem_before); | ||||
|  | ||||
|     furi_hal_usb_lock(); | ||||
|     RpcSession* rpc_session = rpc_session_open(rpc); | ||||
|     if(rpc_session == NULL) { | ||||
|   | ||||
| @@ -346,8 +346,19 @@ void rpc_system_gui_free(void* context) { | ||||
|     } | ||||
|  | ||||
|     if(rpc_gui->is_streaming) { | ||||
|         rpc_gui->is_streaming = false; | ||||
|         // Remove GUI framebuffer callback | ||||
|         gui_remove_framebuffer_callback( | ||||
|             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"); | ||||
|     free(rpc_gui); | ||||
|   | ||||
| @@ -6,6 +6,11 @@ | ||||
|  | ||||
| #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) { | ||||
|     furi_assert(request); | ||||
|     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( | ||||
|     const char* key, | ||||
|     const char* value, | ||||
| @@ -67,7 +67,7 @@ static void rpc_system_system_device_info_callback( | ||||
|     void* context) { | ||||
|     furi_assert(key); | ||||
|     furi_assert(value); | ||||
|     RpcSystemSystemDeviceInfoContext* ctx = context; | ||||
|     RpcSystemContext* ctx = context; | ||||
|  | ||||
|     char* str_key = strdup(key); | ||||
|     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->command_status = PB_CommandStatus_OK; | ||||
|  | ||||
|     RpcSystemSystemDeviceInfoContext device_info_context = { | ||||
|     RpcSystemContext device_info_context = { | ||||
|         .session = session, | ||||
|         .response = response, | ||||
|     }; | ||||
| @@ -202,6 +202,46 @@ static void rpc_system_system_protobuf_version_process(const PB_Main* request, v | ||||
|     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) { | ||||
|     RpcHandler rpc_handler = { | ||||
|         .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_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; | ||||
| } | ||||
|   | ||||
| @@ -42,8 +42,10 @@ void subghz_scene_save_name_on_enter(void* context) { | ||||
|         SUBGHZ_MAX_LEN_NAME + 1, // buffer size | ||||
|         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); | ||||
|  | ||||
|     view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdTextInput); | ||||
|   | ||||
| @@ -400,6 +400,7 @@ bool subghz_rename_file(SubGhz* subghz) { | ||||
|     string_init_printf( | ||||
|         new_path, "%s/%s%s", SUBGHZ_APP_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION); | ||||
|  | ||||
|     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)); | ||||
|  | ||||
| @@ -407,6 +408,7 @@ bool subghz_rename_file(SubGhz* subghz) { | ||||
|             dialog_message_show_storage_error(subghz->dialogs, "Cannot rename\n file/directory"); | ||||
|             ret = false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     string_clear(old_path); | ||||
|     string_clear(new_path); | ||||
|   | ||||
| @@ -98,6 +98,11 @@ typedef struct _PB_Main { | ||||
|         PB_System_PlayAudiovisualAlertRequest system_play_audiovisual_alert_request; | ||||
|         PB_System_ProtobufVersionRequest system_protobuf_version_request; | ||||
|         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;  | ||||
| } PB_Main; | ||||
|  | ||||
| @@ -161,6 +166,11 @@ extern "C" { | ||||
| #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_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 */ | ||||
| #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_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_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_DEFAULT NULL | ||||
| #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_protobuf_version_request_MSGTYPE PB_System_ProtobufVersionRequest | ||||
| #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_StopSession_msg; | ||||
| @@ -266,9 +286,9 @@ extern const pb_msgdesc_t PB_Main_msg; | ||||
| /* Maximum encoded size of messages (where known) */ | ||||
| #define PB_Empty_size                            0 | ||||
| #define PB_StopSession_size                      0 | ||||
| #if defined(PB_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)) | ||||
| 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 | ||||
|  | ||||
| #ifdef __cplusplus | ||||
|   | ||||
| @@ -1,3 +1,3 @@ | ||||
| #pragma once | ||||
| #define PROTOBUF_MAJOR_VERSION 0 | ||||
| #define PROTOBUF_MINOR_VERSION 3 | ||||
| #define PROTOBUF_MINOR_VERSION 5 | ||||
|   | ||||
| @@ -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_BackupCreateRequest, PB_Storage_BackupCreateRequest, AUTO) | ||||
|  | ||||
|  | ||||
| PB_BIND(PB_Storage_BackupRestoreRequest, PB_Storage_BackupRestoreRequest, AUTO) | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -16,6 +16,14 @@ typedef enum _PB_Storage_File_FileType { | ||||
| } PB_Storage_File_FileType; | ||||
|  | ||||
| /* 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 {  | ||||
|     char *path;  | ||||
| } PB_Storage_InfoRequest; | ||||
| @@ -114,6 +122,8 @@ extern "C" { | ||||
| #define PB_Storage_Md5sumRequest_init_default    {NULL} | ||||
| #define PB_Storage_Md5sumResponse_init_default   {""} | ||||
| #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_InfoRequest_init_zero         {NULL} | ||||
| #define PB_Storage_InfoResponse_init_zero        {0, 0} | ||||
| @@ -129,8 +139,12 @@ extern "C" { | ||||
| #define PB_Storage_Md5sumRequest_init_zero       {NULL} | ||||
| #define PB_Storage_Md5sumResponse_init_zero      {""} | ||||
| #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) */ | ||||
| #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_ListRequest_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_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_InfoRequest_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_Md5sumResponse_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 */ | ||||
| #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_Md5sumResponse_fields &PB_Storage_Md5sumResponse_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) */ | ||||
| /* 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_Md5sumRequest_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_Md5sumResponse_size           34 | ||||
|  | ||||
|   | ||||
| @@ -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_UpdateRequest, PB_System_UpdateRequest, AUTO) | ||||
|  | ||||
|  | ||||
| PB_BIND(PB_System_PowerInfoRequest, PB_System_PowerInfoRequest, AUTO) | ||||
|  | ||||
|  | ||||
| PB_BIND(PB_System_PowerInfoResponse, PB_System_PowerInfoResponse, AUTO) | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -45,10 +45,23 @@ typedef struct _PB_System_PlayAudiovisualAlertRequest { | ||||
|     char dummy_field; | ||||
| } 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 {  | ||||
|     char dummy_field; | ||||
| } PB_System_ProtobufVersionRequest; | ||||
|  | ||||
| typedef struct _PB_System_UpdateRequest {  | ||||
|     char *update_folder;  | ||||
| } PB_System_UpdateRequest; | ||||
|  | ||||
| typedef struct _PB_System_DateTime {  | ||||
|     /* Time */ | ||||
|     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_ProtobufVersionRequest_init_default {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_PingResponse_init_zero         {NULL} | ||||
| #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_ProtobufVersionRequest_init_zero {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) */ | ||||
| #define PB_System_DeviceInfoResponse_key_tag     1 | ||||
| #define PB_System_DeviceInfoResponse_value_tag   2 | ||||
| #define PB_System_PingRequest_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_minute_tag            2 | ||||
| #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_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_PingResponse_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_ProtobufVersionRequest_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 */ | ||||
| #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_ProtobufVersionRequest_fields &PB_System_ProtobufVersionRequest_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) */ | ||||
| /* PB_System_PingRequest_size depends on runtime parameters */ | ||||
| /* PB_System_PingResponse_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_DeviceInfoRequest_size         0 | ||||
| #define PB_System_FactoryResetRequest_size       0 | ||||
| #define PB_System_GetDateTimeRequest_size        0 | ||||
| #define PB_System_GetDateTimeResponse_size       24 | ||||
| #define PB_System_PlayAudiovisualAlertRequest_size 0 | ||||
| #define PB_System_PowerInfoRequest_size          0 | ||||
| #define PB_System_ProtobufVersionRequest_size    0 | ||||
| #define PB_System_ProtobufVersionResponse_size   12 | ||||
| #define PB_System_RebootRequest_size             2 | ||||
|   | ||||
 Submodule assets/protobuf updated: cd11b029ac...0403ae1ba7
									
								
							| @@ -15,13 +15,16 @@ | ||||
| #define CRYPTO_TIMEOUT (1000) | ||||
|  | ||||
| #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_INIT (AES_CR_MODE_0 | AES_CR_MODE_1) | ||||
|  | ||||
| #define CRYPTO_DATATYPE_32B 0U | ||||
| #define CRYPTO_KEYSIZE_256B (AES_CR_KEYSIZE) | ||||
| #define CRYPTO_AES_CBC (AES_CR_CHMOD_0) | ||||
|  | ||||
| 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] = { | ||||
|     {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); | ||||
| } | ||||
|  | ||||
| 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) { | ||||
|     crypto_disable(); | ||||
|     CLEAR_BIT(AES1->CR, AES_CR_EN); | ||||
|     MODIFY_REG( | ||||
|         AES1->CR, | ||||
|         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; | ||||
|     } | ||||
|  | ||||
|     furi_hal_crypto_mode_init_done = false; | ||||
|     crypto_key_init(NULL, (uint32_t*)iv); | ||||
|  | ||||
|     if(SHCI_C2_FUS_LoadUsrKey(slot) == SHCI_Success) { | ||||
|         return true; | ||||
|     } else { | ||||
|         crypto_disable(); | ||||
|         CLEAR_BIT(AES1->CR, AES_CR_EN); | ||||
|         furi_check(osMutexRelease(furi_hal_crypto_mutex) == osOK); | ||||
|         return false; | ||||
|     } | ||||
| @@ -270,9 +262,16 @@ bool furi_hal_crypto_store_unload_key(uint8_t slot) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     crypto_disable(); | ||||
|     CLEAR_BIT(AES1->CR, AES_CR_EN); | ||||
|  | ||||
|     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); | ||||
|     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 state = false; | ||||
|  | ||||
|     crypto_enable(); | ||||
|     SET_BIT(AES1->CR, AES_CR_EN); | ||||
|  | ||||
|     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; | ||||
| } | ||||
| @@ -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 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) { | ||||
|         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; | ||||
| } | ||||
|   | ||||
| @@ -239,6 +239,13 @@ uint32_t furi_hal_power_get_battery_full_capacity() { | ||||
|     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 ret = 0.0f; | ||||
|  | ||||
| @@ -399,3 +406,58 @@ void furi_hal_power_suppress_charge_exit() { | ||||
|         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); | ||||
| } | ||||
|   | ||||
| @@ -25,21 +25,32 @@ void furi_hal_speaker_start(float frequency, float volume) { | ||||
|     if(volume > 1) volume = 1; | ||||
|     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}; | ||||
|     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); | ||||
|  | ||||
| #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) { | ||||
|         compare_value = clip_value; | ||||
|     } | ||||
| #else | ||||
|     uint16_t compare_value = volume * TIM_InitStruct.Autoreload / 2; | ||||
|     uint32_t compare_value = volume * autoreload / 2; | ||||
| #endif | ||||
|  | ||||
|     if(compare_value == 0) { | ||||
|         compare_value = 1; | ||||
|     } | ||||
|  | ||||
|     LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; | ||||
|     TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; | ||||
|     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() { | ||||
|     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); | ||||
| } | ||||
|   | ||||
| @@ -113,6 +113,12 @@ uint32_t furi_hal_power_get_battery_remaining_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 | ||||
|  * | ||||
|  * @param      ic    FuriHalPowerIc to get measurment | ||||
| @@ -171,6 +177,23 @@ void furi_hal_power_suppress_charge_enter(); | ||||
|  */ | ||||
| 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 | ||||
| } | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user