Merge remote-tracking branch 'origin/dev' into release-candidate
This commit is contained in:
		
						commit
						e2e4dcc2f8
					
				
							
								
								
									
										11
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @ -96,14 +96,14 @@ jobs: | |||||||
| 
 | 
 | ||||||
|       - name: 'Upload map analyser files to storage' |       - name: 'Upload map analyser files to storage' | ||||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} |         if: ${{ !github.event.pull_request.head.repo.fork }} | ||||||
|         uses: keithweaver/aws-s3-github-action@v1.0.0 |         uses: prewk/s3-cp-action@v2 | ||||||
|         with: |         with: | ||||||
|           source: map_analyser_files/ |           aws_s3_endpoint: "${{ secrets.MAP_REPORT_AWS_ENDPOINT }}" | ||||||
|           destination: "s3://${{ secrets.MAP_REPORT_AWS_BUCKET }}/${{steps.names.outputs.random_hash}}" |  | ||||||
|           aws_access_key_id: "${{ secrets.MAP_REPORT_AWS_ACCESS_KEY }}" |           aws_access_key_id: "${{ secrets.MAP_REPORT_AWS_ACCESS_KEY }}" | ||||||
|           aws_secret_access_key: "${{ secrets.MAP_REPORT_AWS_SECRET_KEY }}" |           aws_secret_access_key: "${{ secrets.MAP_REPORT_AWS_SECRET_KEY }}" | ||||||
|           aws_region: "${{ secrets.MAP_REPORT_AWS_REGION }}" |           source: "./map_analyser_files/" | ||||||
|           flags: --recursive |           dest: "s3://${{ secrets.MAP_REPORT_AWS_BUCKET }}/${{steps.names.outputs.random_hash}}" | ||||||
|  |           flags: "--recursive --acl public-read" | ||||||
| 
 | 
 | ||||||
|       - name: 'Trigger map file reporter' |       - name: 'Trigger map file reporter' | ||||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} |         if: ${{ !github.event.pull_request.head.repo.fork }} | ||||||
| @ -114,7 +114,6 @@ jobs: | |||||||
|           event-type: map-file-analyse |           event-type: map-file-analyse | ||||||
|           client-payload: '{"random_hash": "${{steps.names.outputs.random_hash}}", "event_type": "${{steps.names.outputs.event_type}}"}' |           client-payload: '{"random_hash": "${{steps.names.outputs.random_hash}}", "event_type": "${{steps.names.outputs.event_type}}"}' | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|       - name: 'Upload artifacts to update server' |       - name: 'Upload artifacts to update server' | ||||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} |         if: ${{ !github.event.pull_request.head.repo.fork }} | ||||||
|         run: | |         run: | | ||||||
|  | |||||||
							
								
								
									
										21
									
								
								.github/workflows/pvs_studio.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								.github/workflows/pvs_studio.yml
									
									
									
									
										vendored
									
									
								
							| @ -54,17 +54,16 @@ jobs: | |||||||
|           ./fbt COMPACT=1 PVSNOBROWSER=1 firmware_pvs || WARNINGS=1 |           ./fbt COMPACT=1 PVSNOBROWSER=1 firmware_pvs || WARNINGS=1 | ||||||
|           echo "warnings=${WARNINGS}" >> $GITHUB_OUTPUT |           echo "warnings=${WARNINGS}" >> $GITHUB_OUTPUT | ||||||
| 
 | 
 | ||||||
|       - name: 'Upload artifacts to update server' |       - name: 'Upload report' | ||||||
|         if: ${{ !github.event.pull_request.head.repo.fork && (steps.pvs-warn.outputs.warnings != 0) }} |         if: ${{ !github.event.pull_request.head.repo.fork && (steps.pvs-warn.outputs.warnings != 0) }} | ||||||
|         run: | |         uses: prewk/s3-cp-action@v2 | ||||||
|           mkdir -p ~/.ssh |         with: | ||||||
|           ssh-keyscan -p ${{ secrets.RSYNC_DEPLOY_PORT }} -H ${{ secrets.RSYNC_DEPLOY_HOST }} > ~/.ssh/known_hosts |           aws_s3_endpoint: "${{ secrets.PVS_AWS_ENDPOINT }}" | ||||||
|           echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key; |           aws_access_key_id: "${{ secrets.PVS_AWS_ACCESS_KEY }}" | ||||||
|           chmod 600 ./deploy_key; |           aws_secret_access_key: "${{ secrets.PVS_AWS_SECRET_KEY }}" | ||||||
|           rsync -avrzP --mkpath \ |           source: "./build/f7-firmware-DC/pvsreport" | ||||||
|               -e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \ |           dest: "s3://${{ secrets.PVS_AWS_BUCKET }}/${{steps.names.outputs.branch_name}}/${{steps.names.outputs.default_target}}-${{steps.names.outputs.suffix}}/" | ||||||
|               build/f7-firmware-DC/pvsreport/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:/home/data/firmware-pvs-studio-report/"${BRANCH_NAME}/${{steps.names.outputs.default_target}}-${{steps.names.outputs.suffix}}/"; |           flags: "--recursive --acl public-read" | ||||||
|           rm ./deploy_key; |  | ||||||
| 
 | 
 | ||||||
|       - name: 'Find Previous Comment' |       - name: 'Find Previous Comment' | ||||||
|         if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request && (steps.pvs-warn.outputs.warnings != 0) }} |         if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request && (steps.pvs-warn.outputs.warnings != 0) }} | ||||||
| @ -83,7 +82,7 @@ jobs: | |||||||
|           issue-number: ${{ github.event.pull_request.number }} |           issue-number: ${{ github.event.pull_request.number }} | ||||||
|           body: | |           body: | | ||||||
|             **PVS-Studio report for commit `${{steps.names.outputs.commit_sha}}`:** |             **PVS-Studio report for commit `${{steps.names.outputs.commit_sha}}`:** | ||||||
|             - [Report](https://update.flipperzero.one/builds/firmware-pvs-studio-report/${{steps.names.outputs.branch_name}}/${{steps.names.outputs.default_target}}-${{steps.names.outputs.suffix}}/index.html) |             - [Report](https://pvs.flipp.dev/${{steps.names.outputs.branch_name}}/${{steps.names.outputs.default_target}}-${{steps.names.outputs.suffix}}/index.html) | ||||||
|           edit-mode: replace |           edit-mode: replace | ||||||
| 
 | 
 | ||||||
|       - name: 'Raise exception' |       - name: 'Raise exception' | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| App( | App( | ||||||
|     appid="example_custom_font", |     appid="example_custom_font", | ||||||
|     name="Example: custom font", |     name="Example: custom font", | ||||||
|     apptype=FlipperAppType.EXTERNAL, |     apptype=FlipperAppType.DEBUG, | ||||||
|     entry_point="example_custom_font_main", |     entry_point="example_custom_font_main", | ||||||
|     requires=["gui"], |     requires=["gui"], | ||||||
|     stack_size=1 * 1024, |     stack_size=1 * 1024, | ||||||
|  | |||||||
| @ -115,8 +115,12 @@ BadUsbApp* bad_usb_app_alloc(char* arg) { | |||||||
| 
 | 
 | ||||||
|     if(furi_hal_usb_is_locked()) { |     if(furi_hal_usb_is_locked()) { | ||||||
|         app->error = BadUsbAppErrorCloseRpc; |         app->error = BadUsbAppErrorCloseRpc; | ||||||
|  |         app->usb_if_prev = NULL; | ||||||
|         scene_manager_next_scene(app->scene_manager, BadUsbSceneError); |         scene_manager_next_scene(app->scene_manager, BadUsbSceneError); | ||||||
|     } else { |     } else { | ||||||
|  |         app->usb_if_prev = furi_hal_usb_get_config(); | ||||||
|  |         furi_check(furi_hal_usb_set_config(NULL, NULL)); | ||||||
|  | 
 | ||||||
|         if(!furi_string_empty(app->file_path)) { |         if(!furi_string_empty(app->file_path)) { | ||||||
|             app->bad_usb_script = bad_usb_script_open(app->file_path); |             app->bad_usb_script = bad_usb_script_open(app->file_path); | ||||||
|             bad_usb_script_set_keyboard_layout(app->bad_usb_script, app->keyboard_layout); |             bad_usb_script_set_keyboard_layout(app->bad_usb_script, app->keyboard_layout); | ||||||
| @ -138,6 +142,10 @@ void bad_usb_app_free(BadUsbApp* app) { | |||||||
|         app->bad_usb_script = NULL; |         app->bad_usb_script = NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if(app->usb_if_prev) { | ||||||
|  |         furi_check(furi_hal_usb_set_config(app->usb_if_prev, NULL)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     // Views
 |     // Views
 | ||||||
|     view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork); |     view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork); | ||||||
|     bad_usb_free(app->bad_usb_view); |     bad_usb_free(app->bad_usb_view); | ||||||
|  | |||||||
| @ -14,6 +14,7 @@ | |||||||
| #include <gui/modules/variable_item_list.h> | #include <gui/modules/variable_item_list.h> | ||||||
| #include <gui/modules/widget.h> | #include <gui/modules/widget.h> | ||||||
| #include "views/bad_usb_view.h" | #include "views/bad_usb_view.h" | ||||||
|  | #include <furi_hal_usb.h> | ||||||
| 
 | 
 | ||||||
| #define BAD_USB_APP_BASE_FOLDER ANY_PATH("badusb") | #define BAD_USB_APP_BASE_FOLDER ANY_PATH("badusb") | ||||||
| #define BAD_USB_APP_PATH_LAYOUT_FOLDER BAD_USB_APP_BASE_FOLDER "/assets/layouts" | #define BAD_USB_APP_PATH_LAYOUT_FOLDER BAD_USB_APP_BASE_FOLDER "/assets/layouts" | ||||||
| @ -39,6 +40,8 @@ struct BadUsbApp { | |||||||
|     FuriString* keyboard_layout; |     FuriString* keyboard_layout; | ||||||
|     BadUsb* bad_usb_view; |     BadUsb* bad_usb_view; | ||||||
|     BadUsbScript* bad_usb_script; |     BadUsbScript* bad_usb_script; | ||||||
|  | 
 | ||||||
|  |     FuriHalUsbInterface* usb_if_prev; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|  | |||||||
| @ -490,8 +490,6 @@ static int32_t bad_usb_worker(void* context) { | |||||||
|     BadUsbWorkerState worker_state = BadUsbStateInit; |     BadUsbWorkerState worker_state = BadUsbStateInit; | ||||||
|     int32_t delay_val = 0; |     int32_t delay_val = 0; | ||||||
| 
 | 
 | ||||||
|     FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); |  | ||||||
| 
 |  | ||||||
|     FURI_LOG_I(WORKER_TAG, "Init"); |     FURI_LOG_I(WORKER_TAG, "Init"); | ||||||
|     File* script_file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); |     File* script_file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); | ||||||
|     bad_usb->line = furi_string_alloc(); |     bad_usb->line = furi_string_alloc(); | ||||||
| @ -642,8 +640,6 @@ static int32_t bad_usb_worker(void* context) { | |||||||
| 
 | 
 | ||||||
|     furi_hal_hid_set_state_callback(NULL, NULL); |     furi_hal_hid_set_state_callback(NULL, NULL); | ||||||
| 
 | 
 | ||||||
|     furi_hal_usb_set_config(usb_mode_prev, NULL); |  | ||||||
| 
 |  | ||||||
|     storage_file_close(script_file); |     storage_file_close(script_file); | ||||||
|     storage_file_free(script_file); |     storage_file_free(script_file); | ||||||
|     furi_string_free(bad_usb->line); |     furi_string_free(bad_usb->line); | ||||||
|  | |||||||
| @ -26,7 +26,7 @@ void nfc_magic_scene_wrong_card_on_enter(void* context) { | |||||||
|         AlignLeft, |         AlignLeft, | ||||||
|         AlignTop, |         AlignTop, | ||||||
|         FontSecondary, |         FontSecondary, | ||||||
|         "Writing is supported\nonly for 4 bytes UID\nMifare CLassic 1k"); |         "Writing is supported\nonly for 4 bytes UID\nMifare Classic 1k"); | ||||||
|     widget_add_button_element( |     widget_add_button_element( | ||||||
|         widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wrong_card_widget_callback, nfc_magic); |         widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wrong_card_widget_callback, nfc_magic); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -58,8 +58,12 @@ bool updater_scene_error_on_event(void* context, SceneManagerEvent event) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void updater_scene_error_on_exit(void* context) { | void updater_scene_error_on_exit(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|     Updater* updater = (Updater*)context; |     Updater* updater = (Updater*)context; | ||||||
| 
 | 
 | ||||||
|     widget_reset(updater->widget); |     widget_reset(updater->widget); | ||||||
|     free(updater->pending_update); | 
 | ||||||
|  |     if(updater->loaded_manifest) { | ||||||
|  |         update_manifest_free(updater->loaded_manifest); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -21,11 +21,9 @@ void updater_scene_loadcfg_apply_callback(GuiButtonType result, InputType type, | |||||||
| 
 | 
 | ||||||
| void updater_scene_loadcfg_on_enter(void* context) { | void updater_scene_loadcfg_on_enter(void* context) { | ||||||
|     Updater* updater = (Updater*)context; |     Updater* updater = (Updater*)context; | ||||||
|     UpdaterManifestProcessingState* pending_upd = updater->pending_update = |     UpdateManifest* loaded_manifest = updater->loaded_manifest = update_manifest_alloc(); | ||||||
|         malloc(sizeof(UpdaterManifestProcessingState)); |  | ||||||
|     pending_upd->manifest = update_manifest_alloc(); |  | ||||||
| 
 | 
 | ||||||
|     if(update_manifest_init(pending_upd->manifest, furi_string_get_cstr(updater->startup_arg))) { |     if(update_manifest_init(loaded_manifest, furi_string_get_cstr(updater->startup_arg))) { | ||||||
|         widget_add_string_element( |         widget_add_string_element( | ||||||
|             updater->widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, "Update"); |             updater->widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, "Update"); | ||||||
| 
 | 
 | ||||||
| @ -37,7 +35,7 @@ void updater_scene_loadcfg_on_enter(void* context) { | |||||||
|             32, |             32, | ||||||
|             AlignCenter, |             AlignCenter, | ||||||
|             AlignCenter, |             AlignCenter, | ||||||
|             furi_string_get_cstr(pending_upd->manifest->version), |             furi_string_get_cstr(loaded_manifest->version), | ||||||
|             true); |             true); | ||||||
| 
 | 
 | ||||||
|         widget_add_button_element( |         widget_add_button_element( | ||||||
| @ -95,13 +93,12 @@ bool updater_scene_loadcfg_on_event(void* context, SceneManagerEvent event) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void updater_scene_loadcfg_on_exit(void* context) { | void updater_scene_loadcfg_on_exit(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|     Updater* updater = (Updater*)context; |     Updater* updater = (Updater*)context; | ||||||
| 
 | 
 | ||||||
|     if(updater->pending_update) { |  | ||||||
|         update_manifest_free(updater->pending_update->manifest); |  | ||||||
|         furi_string_free(updater->pending_update->message); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     widget_reset(updater->widget); |     widget_reset(updater->widget); | ||||||
|     free(updater->pending_update); | 
 | ||||||
|  |     if(updater->loaded_manifest) { | ||||||
|  |         update_manifest_free(updater->loaded_manifest); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -33,12 +33,6 @@ typedef enum { | |||||||
|     UpdaterCustomEventSdUnmounted, |     UpdaterCustomEventSdUnmounted, | ||||||
| } UpdaterCustomEvent; | } UpdaterCustomEvent; | ||||||
| 
 | 
 | ||||||
| typedef struct UpdaterManifestProcessingState { |  | ||||||
|     UpdateManifest* manifest; |  | ||||||
|     FuriString* message; |  | ||||||
|     bool ready_to_be_applied; |  | ||||||
| } UpdaterManifestProcessingState; |  | ||||||
| 
 |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     // GUI
 |     // GUI
 | ||||||
|     Gui* gui; |     Gui* gui; | ||||||
| @ -49,7 +43,7 @@ typedef struct { | |||||||
| 
 | 
 | ||||||
|     UpdaterMainView* main_view; |     UpdaterMainView* main_view; | ||||||
| 
 | 
 | ||||||
|     UpdaterManifestProcessingState* pending_update; |     UpdateManifest* loaded_manifest; | ||||||
|     UpdatePrepareResult preparation_result; |     UpdatePrepareResult preparation_result; | ||||||
| 
 | 
 | ||||||
|     UpdateTask* update_task; |     UpdateTask* update_task; | ||||||
|  | |||||||
| @ -41,22 +41,22 @@ typedef struct { | |||||||
| static const UpdateTaskStageGroupMap update_task_stage_progress[] = { | static const UpdateTaskStageGroupMap update_task_stage_progress[] = { | ||||||
|     [UpdateTaskStageProgress] = STAGE_DEF(UpdateTaskStageGroupMisc, 0), |     [UpdateTaskStageProgress] = STAGE_DEF(UpdateTaskStageGroupMisc, 0), | ||||||
| 
 | 
 | ||||||
|     [UpdateTaskStageReadManifest] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 5), |     [UpdateTaskStageReadManifest] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 45), | ||||||
|     [UpdateTaskStageLfsBackup] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 15), |     [UpdateTaskStageLfsBackup] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 5), | ||||||
| 
 | 
 | ||||||
|     [UpdateTaskStageRadioImageValidate] = STAGE_DEF(UpdateTaskStageGroupRadio, 15), |     [UpdateTaskStageRadioImageValidate] = STAGE_DEF(UpdateTaskStageGroupRadio, 15), | ||||||
|     [UpdateTaskStageRadioErase] = STAGE_DEF(UpdateTaskStageGroupRadio, 60), |     [UpdateTaskStageRadioErase] = STAGE_DEF(UpdateTaskStageGroupRadio, 35), | ||||||
|     [UpdateTaskStageRadioWrite] = STAGE_DEF(UpdateTaskStageGroupRadio, 80), |     [UpdateTaskStageRadioWrite] = STAGE_DEF(UpdateTaskStageGroupRadio, 60), | ||||||
|     [UpdateTaskStageRadioInstall] = STAGE_DEF(UpdateTaskStageGroupRadio, 60), |     [UpdateTaskStageRadioInstall] = STAGE_DEF(UpdateTaskStageGroupRadio, 30), | ||||||
|     [UpdateTaskStageRadioBusy] = STAGE_DEF(UpdateTaskStageGroupRadio, 80), |     [UpdateTaskStageRadioBusy] = STAGE_DEF(UpdateTaskStageGroupRadio, 5), | ||||||
| 
 | 
 | ||||||
|     [UpdateTaskStageOBValidation] = STAGE_DEF(UpdateTaskStageGroupOptionBytes, 10), |     [UpdateTaskStageOBValidation] = STAGE_DEF(UpdateTaskStageGroupOptionBytes, 2), | ||||||
| 
 | 
 | ||||||
|     [UpdateTaskStageValidateDFUImage] = STAGE_DEF(UpdateTaskStageGroupFirmware, 50), |     [UpdateTaskStageValidateDFUImage] = STAGE_DEF(UpdateTaskStageGroupFirmware, 30), | ||||||
|     [UpdateTaskStageFlashWrite] = STAGE_DEF(UpdateTaskStageGroupFirmware, 200), |     [UpdateTaskStageFlashWrite] = STAGE_DEF(UpdateTaskStageGroupFirmware, 150), | ||||||
|     [UpdateTaskStageFlashValidate] = STAGE_DEF(UpdateTaskStageGroupFirmware, 30), |     [UpdateTaskStageFlashValidate] = STAGE_DEF(UpdateTaskStageGroupFirmware, 15), | ||||||
| 
 | 
 | ||||||
|     [UpdateTaskStageLfsRestore] = STAGE_DEF(UpdateTaskStageGroupPostUpdate, 30), |     [UpdateTaskStageLfsRestore] = STAGE_DEF(UpdateTaskStageGroupPostUpdate, 5), | ||||||
| 
 | 
 | ||||||
|     [UpdateTaskStageResourcesUpdate] = STAGE_DEF(UpdateTaskStageGroupResources, 255), |     [UpdateTaskStageResourcesUpdate] = STAGE_DEF(UpdateTaskStageGroupResources, 255), | ||||||
|     [UpdateTaskStageSplashscreenInstall] = STAGE_DEF(UpdateTaskStageGroupSplashscreen, 5), |     [UpdateTaskStageSplashscreenInstall] = STAGE_DEF(UpdateTaskStageGroupSplashscreen, 5), | ||||||
|  | |||||||
| @ -41,6 +41,14 @@ static bool update_task_pre_update(UpdateTask* update_task) { | |||||||
|     return success; |     return success; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | typedef enum { | ||||||
|  |     UpdateTaskResourcesWeightsFileCleanup = 20, | ||||||
|  |     UpdateTaskResourcesWeightsDirCleanup = 20, | ||||||
|  |     UpdateTaskResourcesWeightsFileUnpack = 60, | ||||||
|  | } UpdateTaskResourcesWeights; | ||||||
|  | 
 | ||||||
|  | #define UPDATE_TASK_RESOURCES_FILE_TO_TOTAL_PERCENT 90 | ||||||
|  | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     UpdateTask* update_task; |     UpdateTask* update_task; | ||||||
|     int32_t total_files, processed_files; |     int32_t total_files, processed_files; | ||||||
| @ -54,33 +62,36 @@ static bool update_task_resource_unpack_cb(const char* name, bool is_directory, | |||||||
|     update_task_set_progress( |     update_task_set_progress( | ||||||
|         unpack_progress->update_task, |         unpack_progress->update_task, | ||||||
|         UpdateTaskStageProgress, |         UpdateTaskStageProgress, | ||||||
|         /* For this stage, last 70% of progress = extraction */ |         /* For this stage, last progress segment = extraction */ | ||||||
|         30 + (unpack_progress->processed_files * 70) / (unpack_progress->total_files + 1)); |         (UpdateTaskResourcesWeightsFileCleanup + UpdateTaskResourcesWeightsDirCleanup) + | ||||||
|  |             (unpack_progress->processed_files * UpdateTaskResourcesWeightsFileUnpack) / | ||||||
|  |                 (unpack_progress->total_files + 1)); | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void update_task_cleanup_resources(UpdateTask* update_task, const uint32_t n_tar_entries) { | ||||||
|     update_task_cleanup_resources(UpdateTask* update_task, uint32_t n_approx_file_entries) { |  | ||||||
|     ResourceManifestReader* manifest_reader = resource_manifest_reader_alloc(update_task->storage); |     ResourceManifestReader* manifest_reader = resource_manifest_reader_alloc(update_task->storage); | ||||||
|     do { |     do { | ||||||
|         FURI_LOG_I(TAG, "Cleaning up old manifest"); |         FURI_LOG_D(TAG, "Cleaning up old manifest"); | ||||||
|         if(!resource_manifest_reader_open(manifest_reader, EXT_PATH("Manifest"))) { |         if(!resource_manifest_reader_open(manifest_reader, EXT_PATH("Manifest"))) { | ||||||
|             FURI_LOG_W(TAG, "No existing manifest"); |             FURI_LOG_W(TAG, "No existing manifest"); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /* We got # of entries in TAR file. Approx 1/4th is dir entries, we skip them */ |         const uint32_t n_approx_file_entries = | ||||||
|         n_approx_file_entries = n_approx_file_entries * 3 / 4 + 1; |             n_tar_entries * UPDATE_TASK_RESOURCES_FILE_TO_TOTAL_PERCENT / 100 + 1; | ||||||
|         uint32_t n_processed_files = 0; |         uint32_t n_dir_entries = 1; | ||||||
| 
 | 
 | ||||||
|         ResourceManifestEntry* entry_ptr = NULL; |         ResourceManifestEntry* entry_ptr = NULL; | ||||||
|  |         uint32_t n_processed_entries = 0; | ||||||
|         while((entry_ptr = resource_manifest_reader_next(manifest_reader))) { |         while((entry_ptr = resource_manifest_reader_next(manifest_reader))) { | ||||||
|             if(entry_ptr->type == ResourceManifestEntryTypeFile) { |             if(entry_ptr->type == ResourceManifestEntryTypeFile) { | ||||||
|                 update_task_set_progress( |                 update_task_set_progress( | ||||||
|                     update_task, |                     update_task, | ||||||
|                     UpdateTaskStageProgress, |                     UpdateTaskStageProgress, | ||||||
|                     /* For this stage, first 20% of progress = cleanup files */ |                     /* For this stage, first pass = old manifest's file cleanup */ | ||||||
|                     (n_processed_files++ * 20) / (n_approx_file_entries + 1)); |                     (n_processed_entries++ * UpdateTaskResourcesWeightsFileCleanup) / | ||||||
|  |                         n_approx_file_entries); | ||||||
| 
 | 
 | ||||||
|                 FuriString* file_path = furi_string_alloc(); |                 FuriString* file_path = furi_string_alloc(); | ||||||
|                 path_concat( |                 path_concat( | ||||||
| @ -88,16 +99,21 @@ static void | |||||||
|                 FURI_LOG_D(TAG, "Removing %s", furi_string_get_cstr(file_path)); |                 FURI_LOG_D(TAG, "Removing %s", furi_string_get_cstr(file_path)); | ||||||
|                 storage_simply_remove(update_task->storage, furi_string_get_cstr(file_path)); |                 storage_simply_remove(update_task->storage, furi_string_get_cstr(file_path)); | ||||||
|                 furi_string_free(file_path); |                 furi_string_free(file_path); | ||||||
|  |             } else if(entry_ptr->type == ResourceManifestEntryTypeDirectory) { | ||||||
|  |                 n_dir_entries++; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         n_processed_entries = 0; | ||||||
|         while((entry_ptr = resource_manifest_reader_previous(manifest_reader))) { |         while((entry_ptr = resource_manifest_reader_previous(manifest_reader))) { | ||||||
|             if(entry_ptr->type == ResourceManifestEntryTypeDirectory) { |             if(entry_ptr->type == ResourceManifestEntryTypeDirectory) { | ||||||
|                 update_task_set_progress( |                 update_task_set_progress( | ||||||
|                     update_task, |                     update_task, | ||||||
|                     UpdateTaskStageProgress, |                     UpdateTaskStageProgress, | ||||||
|                     /* For this stage, second 10% of progress = cleanup directories */ |                     /* For this stage, second 10% of progress = cleanup directories */ | ||||||
|                     (n_processed_files++ * 10) / (n_approx_file_entries + 1)); |                     UpdateTaskResourcesWeightsFileCleanup + | ||||||
|  |                         (n_processed_entries++ * UpdateTaskResourcesWeightsDirCleanup) / | ||||||
|  |                             n_dir_entries); | ||||||
| 
 | 
 | ||||||
|                 FuriString* folder_path = furi_string_alloc(); |                 FuriString* folder_path = furi_string_alloc(); | ||||||
|                 File* folder_file = storage_file_alloc(update_task->storage); |                 File* folder_file = storage_file_alloc(update_task->storage); | ||||||
|  | |||||||
| @ -340,7 +340,7 @@ static void usb_process_mode_start(FuriHalUsbInterface* interface, void* context | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void usb_process_mode_change(FuriHalUsbInterface* interface, void* context) { | static void usb_process_mode_change(FuriHalUsbInterface* interface, void* context) { | ||||||
|     if(interface != usb.interface) { |     if((interface != usb.interface) || (context != usb.interface_context)) { | ||||||
|         if(usb.enabled) { |         if(usb.enabled) { | ||||||
|             // Disable current interface
 |             // Disable current interface
 | ||||||
|             susp_evt(&udev, 0, 0); |             susp_evt(&udev, 0, 0); | ||||||
|  | |||||||
| @ -237,10 +237,8 @@ void ibutton_worker_emulate_timer_cb(void* context) { | |||||||
|     const LevelDuration level_duration = |     const LevelDuration level_duration = | ||||||
|         protocol_dict_encoder_yield(worker->protocols, worker->protocol_to_encode); |         protocol_dict_encoder_yield(worker->protocols, worker->protocol_to_encode); | ||||||
| 
 | 
 | ||||||
|     const bool level = level_duration_get_level(level_duration); |     furi_hal_ibutton_emulate_set_next(level_duration_get_duration(level_duration)); | ||||||
| 
 |     furi_hal_ibutton_pin_write(level_duration_get_level(level_duration)); | ||||||
|     furi_hal_ibutton_emulate_set_next(level); |  | ||||||
|     furi_hal_ibutton_pin_write(level); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ibutton_worker_emulate_timer_start(iButtonWorker* worker) { | void ibutton_worker_emulate_timer_start(iButtonWorker* worker) { | ||||||
|  | |||||||
| @ -106,6 +106,7 @@ void tar_archive_set_file_callback(TarArchive* archive, tar_unpack_file_cb callb | |||||||
| static int tar_archive_entry_counter(mtar_t* tar, const mtar_header_t* header, void* param) { | static int tar_archive_entry_counter(mtar_t* tar, const mtar_header_t* header, void* param) { | ||||||
|     UNUSED(tar); |     UNUSED(tar); | ||||||
|     UNUSED(header); |     UNUSED(header); | ||||||
|  |     furi_assert(param); | ||||||
|     int32_t* counter = param; |     int32_t* counter = param; | ||||||
|     (*counter)++; |     (*counter)++; | ||||||
|     return 0; |     return 0; | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| from SCons.Builder import Builder | from SCons.Builder import Builder | ||||||
| from SCons.Action import Action | from SCons.Action import Action | ||||||
| from SCons.Script import Delete, Mkdir, GetBuildFailures | from SCons.Script import Delete, Mkdir, GetBuildFailures, Flatten | ||||||
| import multiprocessing | import multiprocessing | ||||||
| import webbrowser | import webbrowser | ||||||
| import atexit | import atexit | ||||||
| @ -30,12 +30,13 @@ def atexist_handler(): | |||||||
|         return |         return | ||||||
| 
 | 
 | ||||||
|     for bf in GetBuildFailures(): |     for bf in GetBuildFailures(): | ||||||
|         if bf.node.exists and bf.node.name.endswith(".html"): |         for node in Flatten(bf.node): | ||||||
|  |             if node.exists and node.name.endswith(".html"): | ||||||
|                 # macOS |                 # macOS | ||||||
|                 if sys.platform == "darwin": |                 if sys.platform == "darwin": | ||||||
|                 subprocess.run(["open", bf.node.abspath]) |                     subprocess.run(["open", node.abspath]) | ||||||
|                 else: |                 else: | ||||||
|                 webbrowser.open(bf.node.abspath) |                     webbrowser.open(node.abspath) | ||||||
|                 break |                 break | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -17,7 +17,7 @@ def parse_args(): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def checkCommitMessage(msg): | def checkCommitMessage(msg): | ||||||
|     regex = re.compile(r"^'?\[FL-\d+\]") |     regex = re.compile(r"^'?\[(FL-\d+,?\s?)+\]") | ||||||
|     if regex.match(msg): |     if regex.match(msg): | ||||||
|         return True |         return True | ||||||
|     return False |     return False | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Aleksandr Kutuzov
						Aleksandr Kutuzov