[FL-2627] Flipper applications: SDK, build and debug system (#1387)
* Added support for running applications from SD card (FAPs - Flipper Application Packages) * Added plugin_dist target for fbt to build FAPs * All apps of type FlipperAppType.EXTERNAL and FlipperAppType.PLUGIN are built as FAPs by default * Updated VSCode configuration for new fbt features - re-deploy stock configuration to use them * Added debugging support for FAPs with fbt debug & VSCode * Added public firmware API with automated versioning Co-authored-by: hedger <hedger@users.noreply.github.com> Co-authored-by: SG <who.just.the.doctor@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									0f6f9ad52e
								
							
						
					
					
						commit
						b9a766d909
					
				
							
								
								
									
										131
									
								
								.clang-format
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								.clang-format
									
									
									
									
									
								
							| @ -1,86 +1,191 @@ | ||||
| --- | ||||
| Language:        Cpp | ||||
| AccessModifierOffset: -4 | ||||
| AlignAfterOpenBracket: AlwaysBreak | ||||
| AlignConsecutiveAssignments: false | ||||
| AlignConsecutiveDeclarations: false | ||||
| AlignArrayOfStructures: None | ||||
| AlignConsecutiveMacros: None | ||||
| AlignConsecutiveAssignments: None | ||||
| AlignConsecutiveBitFields: None | ||||
| AlignConsecutiveDeclarations: None | ||||
| AlignEscapedNewlines: Left | ||||
| AlignOperands: true | ||||
| AlignOperands:   Align | ||||
| AlignTrailingComments: false | ||||
| AllowAllArgumentsOnNextLine: true | ||||
| AllowAllParametersOfDeclarationOnNextLine: false | ||||
| AllowShortEnumsOnASingleLine: true | ||||
| AllowShortBlocksOnASingleLine: Never | ||||
| AllowShortCaseLabelsOnASingleLine: false | ||||
| AllowShortFunctionsOnASingleLine: None | ||||
| AllowShortIfStatementsOnASingleLine: true | ||||
| AllowShortLambdasOnASingleLine: All | ||||
| AllowShortIfStatementsOnASingleLine: WithoutElse | ||||
| AllowShortLoopsOnASingleLine: true | ||||
| AlwaysBreakAfterDefinitionReturnType: None | ||||
| AlwaysBreakAfterReturnType: None | ||||
| AlwaysBreakBeforeMultilineStrings: false | ||||
| AlwaysBreakTemplateDeclarations: false | ||||
| AlwaysBreakTemplateDeclarations: Yes | ||||
| AttributeMacros: | ||||
|   - __capability | ||||
| BinPackArguments: false | ||||
| BinPackParameters: false | ||||
| BraceWrapping: | ||||
|   AfterCaseLabel:  false | ||||
|   AfterClass:      false | ||||
|   AfterControlStatement: Never | ||||
|   AfterEnum:       false | ||||
|   AfterFunction:   false | ||||
|   AfterNamespace:  false | ||||
|   AfterObjCDeclaration: false | ||||
|   AfterStruct:     false | ||||
|   AfterUnion:      false | ||||
|   AfterExternBlock: false | ||||
|   BeforeCatch:     false | ||||
|   BeforeElse:      false | ||||
|   BeforeLambdaBody: false | ||||
|   BeforeWhile:     false | ||||
|   IndentBraces:    false | ||||
|   SplitEmptyFunction: true | ||||
|   SplitEmptyRecord: true | ||||
|   SplitEmptyNamespace: true | ||||
| BreakBeforeBinaryOperators: None | ||||
| BreakBeforeConceptDeclarations: true | ||||
| BreakBeforeBraces: Attach | ||||
| BreakBeforeInheritanceComma: false | ||||
| BreakInheritanceList: BeforeColon | ||||
| BreakBeforeTernaryOperators: false | ||||
| BreakConstructorInitializersBeforeComma: false | ||||
| BreakConstructorInitializers: BeforeComma | ||||
| BreakAfterJavaFieldAnnotations: false | ||||
| BreakStringLiterals: false | ||||
| ColumnLimit:     99 | ||||
| CommentPragmas:  '^ IWYU pragma:' | ||||
| QualifierAlignment: Leave | ||||
| CompactNamespaces: false | ||||
| ConstructorInitializerAllOnOneLineOrOnePerLine: false | ||||
| ConstructorInitializerIndentWidth: 4 | ||||
| ContinuationIndentWidth: 4 | ||||
| Cpp11BracedListStyle: true | ||||
| DeriveLineEnding: true | ||||
| DerivePointerAlignment: false | ||||
| DisableFormat:   false | ||||
| EmptyLineAfterAccessModifier: Never | ||||
| EmptyLineBeforeAccessModifier: LogicalBlock | ||||
| ExperimentalAutoDetectBinPacking: false | ||||
| PackConstructorInitializers: BinPack | ||||
| BasedOnStyle:    '' | ||||
| ConstructorInitializerAllOnOneLineOrOnePerLine: false | ||||
| AllowAllConstructorInitializersOnNextLine: true | ||||
| FixNamespaceComments: false | ||||
| 
 | ||||
| ForEachMacros: | ||||
|   - foreach | ||||
|   - Q_FOREACH | ||||
|   - BOOST_FOREACH | ||||
| IfMacros: | ||||
|   - KJ_IF_MAYBE | ||||
| IncludeBlocks:   Preserve | ||||
| IncludeCategories: | ||||
|   - Regex:           '.*' | ||||
|     Priority:        1 | ||||
|     SortPriority:    0 | ||||
|     CaseSensitive:   false | ||||
|   - Regex:           '^(<|"(gtest|gmock|isl|json)/)' | ||||
|     Priority:        3 | ||||
|     SortPriority:    0 | ||||
|     CaseSensitive:   false | ||||
|   - Regex:           '.*' | ||||
|     Priority:        1 | ||||
|     SortPriority:    0 | ||||
|     CaseSensitive:   false | ||||
| IncludeIsMainRegex: '(Test)?$' | ||||
| IncludeIsMainSourceRegex: '' | ||||
| IndentAccessModifiers: false | ||||
| IndentCaseLabels: false | ||||
| IndentCaseBlocks: false | ||||
| IndentGotoLabels: true | ||||
| IndentPPDirectives: None | ||||
| IndentExternBlock: AfterExternBlock | ||||
| IndentRequires:  false | ||||
| IndentWidth:     4 | ||||
| IndentWrappedFunctionNames: true | ||||
| InsertTrailingCommas: None | ||||
| JavaScriptQuotes: Leave | ||||
| JavaScriptWrapImports: true | ||||
| KeepEmptyLinesAtTheStartOfBlocks: false | ||||
| LambdaBodyIndentation: Signature | ||||
| MacroBlockBegin: '' | ||||
| MacroBlockEnd:   '' | ||||
| MaxEmptyLinesToKeep: 1 | ||||
| NamespaceIndentation: None | ||||
| ObjCBinPackProtocolList: Auto | ||||
| ObjCBlockIndentWidth: 4 | ||||
| ObjCBreakBeforeNestedBlockParam: true | ||||
| ObjCSpaceAfterProperty: true | ||||
| ObjCSpaceBeforeProtocolList: true | ||||
| 
 | ||||
| # Taken from git's rules | ||||
| PenaltyBreakAssignment: 10 | ||||
| PenaltyBreakBeforeFirstCallParameter: 30 | ||||
| PenaltyBreakComment: 10 | ||||
| PenaltyBreakFirstLessLess: 0 | ||||
| PenaltyBreakOpenParenthesis: 0 | ||||
| PenaltyBreakString: 10 | ||||
| PenaltyBreakTemplateDeclaration: 10 | ||||
| PenaltyExcessCharacter: 100 | ||||
| PenaltyReturnTypeOnItsOwnLine: 60 | ||||
| 
 | ||||
| PenaltyIndentedWhitespace: 0 | ||||
| PointerAlignment: Left | ||||
| PPIndentWidth:   -1 | ||||
| ReferenceAlignment: Pointer | ||||
| ReflowComments:  false | ||||
| SortIncludes: false | ||||
| RemoveBracesLLVM: false | ||||
| SeparateDefinitionBlocks: Leave | ||||
| ShortNamespaceLines: 1 | ||||
| SortIncludes:    Never | ||||
| SortJavaStaticImport: Before | ||||
| SortUsingDeclarations: false | ||||
| SpaceAfterCStyleCast: false | ||||
| SpaceAfterLogicalNot: false | ||||
| SpaceAfterTemplateKeyword: true | ||||
| SpaceBeforeAssignmentOperators: true | ||||
| SpaceBeforeCaseColon: false | ||||
| SpaceBeforeCpp11BracedList: false | ||||
| SpaceBeforeCtorInitializerColon: true | ||||
| SpaceBeforeInheritanceColon: true | ||||
| SpaceBeforeParens: Never | ||||
| SpaceBeforeParensOptions: | ||||
|   AfterControlStatements: false | ||||
|   AfterForeachMacros: false | ||||
|   AfterFunctionDefinitionName: false | ||||
|   AfterFunctionDeclarationName: false | ||||
|   AfterIfMacros:   false | ||||
|   AfterOverloadedOperator: false | ||||
|   BeforeNonEmptyParentheses: false | ||||
| SpaceAroundPointerQualifiers: Default | ||||
| SpaceBeforeRangeBasedForLoopColon: true | ||||
| SpaceInEmptyBlock: false | ||||
| SpaceInEmptyParentheses: false | ||||
| SpacesBeforeTrailingComments: 1 | ||||
| SpacesInAngles: false | ||||
| SpacesInAngles:  Never | ||||
| SpacesInConditionalStatement: false | ||||
| SpacesInContainerLiterals: false | ||||
| SpacesInCStyleCastParentheses: false | ||||
| SpacesInLineCommentPrefix: | ||||
|   Minimum:         1 | ||||
|   Maximum:         -1 | ||||
| SpacesInParentheses: false | ||||
| SpacesInSquareBrackets: false | ||||
| Standard: Cpp03 | ||||
| SpaceBeforeSquareBrackets: false | ||||
| BitFieldColonSpacing: Both | ||||
| Standard:        c++03 | ||||
| StatementAttributeLikeMacros: | ||||
|   - Q_EMIT | ||||
| StatementMacros: | ||||
|   - Q_UNUSED | ||||
|   - QT_REQUIRE_VERSION | ||||
| TabWidth:        4 | ||||
| UseCRLF:         false | ||||
| UseTab:          Never | ||||
| WhitespaceSensitiveMacros: | ||||
|   - STRINGIZE | ||||
|   - PP_STRINGIZE | ||||
|   - BOOST_PP_STRINGIZE | ||||
|   - NS_SWIFT_NAME | ||||
|   - CF_SWIFT_NAME | ||||
| ... | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @ -28,3 +28,6 @@ | ||||
| [submodule "lib/mbedtls"] | ||||
| 	path = lib/mbedtls | ||||
| 	url = https://github.com/Mbed-TLS/mbedtls.git | ||||
| [submodule "lib/cxxheaderparser"] | ||||
| 	path = lib/cxxheaderparser | ||||
| 	url = https://github.com/robotpy/cxxheaderparser.git | ||||
|  | ||||
							
								
								
									
										13
									
								
								.vscode/example/launch.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								.vscode/example/launch.json
									
									
									
									
										vendored
									
									
								
							| @ -31,7 +31,10 @@ | ||||
|             ], | ||||
|             "postAttachCommands": [ | ||||
|                 // "attach 1", | ||||
|                 "compare-sections", | ||||
|                 // "compare-sections", | ||||
|                 "source debug/flipperapps.py", | ||||
|                 // "source debug/FreeRTOS/FreeRTOS.py", | ||||
|                 // "svd_load debug/STM32WB55_CM4.svd" | ||||
|             ] | ||||
|             // "showDevDebugOutput": "raw", | ||||
|         }, | ||||
| @ -50,7 +53,8 @@ | ||||
|                 "attach 1", | ||||
|                 "set confirm off", | ||||
|                 "set mem inaccessible-by-default off", | ||||
|                 "compare-sections", | ||||
|                 "source debug/flipperapps.py", | ||||
|                 // "compare-sections", | ||||
|             ] | ||||
|             // "showDevDebugOutput": "raw", | ||||
|         }, | ||||
| @ -65,6 +69,9 @@ | ||||
|             "device": "STM32WB55RG", | ||||
|             "svdFile": "./debug/STM32WB55_CM4.svd", | ||||
|             "rtos": "FreeRTOS", | ||||
|             "postAttachCommands": [ | ||||
|                 "source debug/flipperapps.py", | ||||
|             ] | ||||
|             // "showDevDebugOutput": "raw", | ||||
|         }, | ||||
|         { | ||||
| @ -73,7 +80,7 @@ | ||||
|             "request": "launch", | ||||
|             "program": "./lib/scons/scripts/scons.py", | ||||
|             "args": [ | ||||
|                 "sdk" | ||||
|                 "plugin_dist" | ||||
|             ] | ||||
|         }, | ||||
|         { | ||||
|  | ||||
							
								
								
									
										3
									
								
								.vscode/example/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.vscode/example/settings.json
									
									
									
									
										vendored
									
									
								
							| @ -12,6 +12,9 @@ | ||||
|     "cortex-debug.openocdPath.windows": "${workspaceFolder}/toolchain/i686-windows/openocd/bin/openocd.exe", | ||||
|     "cortex-debug.openocdPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/openocd/bin/openocd", | ||||
|     "cortex-debug.openocdPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/openocd/bin/openocd", | ||||
|     "cortex-debug.gdbPath.windows": "${workspaceFolder}/toolchain/i686-windows/bin/arm-none-eabi-gdb-py.bat", | ||||
|     "cortex-debug.gdbPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gdb-py", | ||||
|     "cortex-debug.gdbPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gdb", | ||||
|     "editor.formatOnSave": true, | ||||
|     "files.associations": { | ||||
|         "*.scons": "python", | ||||
|  | ||||
							
								
								
									
										30
									
								
								.vscode/example/tasks.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								.vscode/example/tasks.json
									
									
									
									
										vendored
									
									
								
							| @ -93,11 +93,41 @@ | ||||
|             "type": "shell", | ||||
|             "command": "./fbt FIRMWARE_APP_SET=unit_tests FORCE=1 flash_usb" | ||||
|         }, | ||||
|         { | ||||
|             "label": "[Debug] Flash (USB, with resources)", | ||||
|             "group": "build", | ||||
|             "type": "shell", | ||||
|             "command": "./fbt FORCE=1 flash_usb_full" | ||||
|         }, | ||||
|         { | ||||
|             "label": "[Release] Flash (USB, with resources)", | ||||
|             "group": "build", | ||||
|             "type": "shell", | ||||
|             "command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb_full" | ||||
|         }, | ||||
|         { | ||||
|             "label": "[Debug] Build FAPs", | ||||
|             "group": "build", | ||||
|             "type": "shell", | ||||
|             "command": "./fbt plugin_dist" | ||||
|         }, | ||||
|         { | ||||
|             "label": "[Release] Build FAPs", | ||||
|             "group": "build", | ||||
|             "type": "shell", | ||||
|             "command": "./fbt COMPACT=1 DEBUG=0 plugin_dist" | ||||
|         }, | ||||
|         { | ||||
|             "label": "[Debug] Launch App on Flipper", | ||||
|             "group": "build", | ||||
|             "type": "shell", | ||||
|             "command": "./fbt launch_app APPSRC=${relativeFileDirname}" | ||||
|         }, | ||||
|         { | ||||
|             "label": "[Release] Launch App on Flipper", | ||||
|             "group": "build", | ||||
|             "type": "shell", | ||||
|             "command": "./fbt COMPACT=1 DEBUG=0 launch_app APPSRC=${relativeFileDirname}" | ||||
|         } | ||||
|     ] | ||||
| } | ||||
| @ -14,6 +14,10 @@ You should clone with | ||||
| $ git clone --recursive https://github.com/flipperdevices/flipperzero-firmware.git | ||||
| ``` | ||||
| 
 | ||||
| # Read the Docs | ||||
| 
 | ||||
| Check out details on [how to build firmware](documentation/fbt.md), [write applications](documentation/AppsOnSDCard.md), [un-brick your device](documentation/KeyCombo.md) and more in `documentation` folder.  | ||||
| 
 | ||||
| # Update firmware | ||||
| 
 | ||||
| [Get Latest Firmware from Update Server](https://update.flipperzero.one/) | ||||
|  | ||||
							
								
								
									
										28
									
								
								SConstruct
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								SConstruct
									
									
									
									
									
								
							| @ -9,9 +9,10 @@ | ||||
| import os | ||||
| import subprocess | ||||
| 
 | ||||
| DefaultEnvironment(tools=[]) | ||||
| 
 | ||||
| EnsurePythonVersion(3, 8) | ||||
| 
 | ||||
| DefaultEnvironment(tools=[]) | ||||
| # Progress(["OwO\r", "owo\r", "uwu\r", "owo\r"], interval=15) | ||||
| 
 | ||||
| 
 | ||||
| @ -58,6 +59,8 @@ distenv = coreenv.Clone( | ||||
|         "-ex", | ||||
|         "source debug/FreeRTOS/FreeRTOS.py", | ||||
|         "-ex", | ||||
|         "source debug/flipperapps.py", | ||||
|         "-ex", | ||||
|         "source debug/PyCortexMDebug/PyCortexMDebug.py", | ||||
|         "-ex", | ||||
|         "svd_load ${SVD_FILE}", | ||||
| @ -160,6 +163,28 @@ if GetOption("fullenv") or any( | ||||
| basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"]) | ||||
| distenv.Default(basic_dist) | ||||
| 
 | ||||
| dist_dir = distenv.GetProjetDirName() | ||||
| plugin_dist = [ | ||||
|     distenv.Install( | ||||
|         f"#/dist/{dist_dir}/apps/debug_elf", | ||||
|         firmware_env["FW_EXTAPPS"]["debug"].values(), | ||||
|     ), | ||||
|     *( | ||||
|         distenv.Install(f"#/dist/{dist_dir}/apps/{dist_entry[0]}", dist_entry[1]) | ||||
|         for dist_entry in firmware_env["FW_EXTAPPS"]["dist"].values() | ||||
|     ), | ||||
| ] | ||||
| Depends(plugin_dist, firmware_env["FW_EXTAPPS"]["validators"].values()) | ||||
| Alias("plugin_dist", plugin_dist) | ||||
| # distenv.Default(plugin_dist) | ||||
| 
 | ||||
| plugin_resources_dist = list( | ||||
|     distenv.Install(f"#/assets/resources/apps/{dist_entry[0]}", dist_entry[1]) | ||||
|     for dist_entry in firmware_env["FW_EXTAPPS"]["dist"].values() | ||||
| ) | ||||
| distenv.Depends(firmware_env["FW_RESOURCES"], plugin_resources_dist) | ||||
| 
 | ||||
| 
 | ||||
| # Target for bundling core2 package for qFlipper | ||||
| copro_dist = distenv.CoproBuilder( | ||||
|     distenv.Dir("assets/core2_firmware"), | ||||
| @ -240,7 +265,6 @@ firmware_env.Append( | ||||
|         "site_scons", | ||||
|         "scripts", | ||||
|         # Extra files | ||||
|         "applications/extapps.scons", | ||||
|         "SConstruct", | ||||
|         "firmware.scons", | ||||
|         "fbt_options.py", | ||||
|  | ||||
| @ -1,38 +1,90 @@ | ||||
| # Structure | ||||
| 
 | ||||
| - `about`               - Small About application that shows flipper info | ||||
| - `application.h`       - Firmware application list header | ||||
| 
 | ||||
| 
 | ||||
| ## debug  | ||||
| 
 | ||||
| Applications for factory testing the Flipper. | ||||
| 
 | ||||
| - `accessor`            - Wiegand server  | ||||
| - `battery_test_app`    - Battery debug app | ||||
| - `blink_test`          - LED blinker    | ||||
| - `bt_debug_app`        - BT test app. Requires full BT stack installed | ||||
| - `display_test`        - Various display tests & tweaks | ||||
| - `file_browser_test`   - Test UI for file picker | ||||
| - `keypad_test`         - Keypad test | ||||
| - `lfrfid_debug`        - LF RFID debug tool | ||||
| - `text_box_test`       - UI tests | ||||
| - `uart_echo`           - UART mode test  | ||||
| - `unit_tests`          - Unit tests | ||||
| - `usb_mouse`           - USB HID test | ||||
| - `usb_test`            - Other USB tests | ||||
| - `vibro_test`          - Vibro test | ||||
| 
 | ||||
| 
 | ||||
| ## main | ||||
| 
 | ||||
| Applications for main Flipper menu. | ||||
| 
 | ||||
| - `archive`             - Archive and file manager  | ||||
| - `bad_usb`             - Bad USB application | ||||
| - `fap_loader`          - External applications loader | ||||
| - `gpio`                - GPIO application: includes USART bridge and GPIO control | ||||
| - `ibutton`             - iButton application, onewire keys and more | ||||
| - `infrared`            - Infrared application, controls your IR devices | ||||
| - `lfrfid`              - LF RFID application | ||||
| - `nfc`                 - NFC application, HF rfid, EMV and etc | ||||
| - `subghz`              - SubGhz application, 433 fobs and etc | ||||
| - `u2f`                 - U2F Application | ||||
| 
 | ||||
| 
 | ||||
| ## plugins | ||||
| 
 | ||||
| Extra apps for Plugins & App Loader menus. | ||||
| 
 | ||||
| - `bt_hid_app`          - BT Remote controller | ||||
| - `music_player`        - Music player app (demo) | ||||
| - `picopass`            - Picopass tool | ||||
| - `snake_game`          - Snake game application | ||||
| 
 | ||||
| 
 | ||||
| ## services | ||||
| 
 | ||||
| Background services providing system APIs to applications. | ||||
| 
 | ||||
| - `bt`                  - BLE service and application | ||||
| - `cli`                 - Console service and API | ||||
| - `crypto`              - Crypto cli tools | ||||
| - `debug_tools`         - Different tools that we use for debug | ||||
| - `desktop`             - Desktop service | ||||
| - `dialogs`             - Dialogs service: GUI Dialogs for your app | ||||
| - `dolphin`             - Dolphin service and supplementary apps | ||||
| - `gpio`                - GPIO application: includes USART bridge and GPIO control | ||||
| - `gui`                 - GUI service and API | ||||
| - `ibutton`             - iButton application, onewire keys and more | ||||
| - `input`               - Input service | ||||
| - `infrared`            - Infrared application, controls your IR devices | ||||
| - `lfrfid`              - LF RFID application | ||||
| - `lfrfid_debug`        - LF RFID debug tool | ||||
| - `loader`              - Application loader service | ||||
| - `music_player`        - Music player app (demo) | ||||
| - `nfc`                 - NFC application, HF rfid, EMV and etc | ||||
| - `notification`        - Notification service  | ||||
| - `power`               - Power service | ||||
| - `power_observer`      - Power debug tool | ||||
| - `rpc`                 - RPC service and API | ||||
| - `scened_app_example`  - C++ application example | ||||
| - `snake_game`          - Snake game application | ||||
| - `storage`             - Storage service, internal + sdcard | ||||
| - `storage_settings`    - Storage settings app | ||||
| - `subghz`              - SubGhz application, 433 fobs and etc | ||||
| - `system`              - System settings, tools and API | ||||
| - `tests`               - Unit tests and etc | ||||
| - `u2f`                 - U2F Application | ||||
| - `updater`             - Update service & application | ||||
| 
 | ||||
| - `application.h`       - Firmware application list header | ||||
| 
 | ||||
| ## settings | ||||
| 
 | ||||
| Small applications providing configuration for basic firmware and its services. | ||||
| 
 | ||||
| - `about`               - Small About application that shows flipper info | ||||
| - `bt_settings_app`     - Bluetooth options | ||||
| - `desktop_settings`    - Desktop configuration | ||||
| - `dolphin_passport`    - Dolphin passport app | ||||
| - `notification_settings` - LCD brightness, sound volume, etc configuration | ||||
| - `power_settings_app`  - Basic power options | ||||
| - `storage_settings`    - Storage settings app | ||||
| - `system`              - System settings | ||||
| 
 | ||||
| 
 | ||||
| ## system | ||||
| 
 | ||||
| Utility apps not visible in other menus. | ||||
| 
 | ||||
| - `storage_move_to_sd`  - Data migration tool for internal storage | ||||
| - `updater`             - Update service & application | ||||
|  | ||||
| @ -1,66 +0,0 @@ | ||||
| App( | ||||
|     appid="bt", | ||||
|     name="BtSrv", | ||||
|     apptype=FlipperAppType.SERVICE, | ||||
|     entry_point="bt_srv", | ||||
|     cdefines=["SRV_BT"], | ||||
|     requires=[ | ||||
|         "cli", | ||||
|         "dialogs", | ||||
|     ], | ||||
|     provides=[ | ||||
|         "bt_start", | ||||
|         "bt_settings", | ||||
|         "bt_debug", | ||||
|     ], | ||||
|     stack_size=1 * 1024, | ||||
|     order=20, | ||||
| ) | ||||
| 
 | ||||
| App( | ||||
|     appid="bt_start", | ||||
|     apptype=FlipperAppType.STARTUP, | ||||
|     entry_point="bt_on_system_start", | ||||
|     order=70, | ||||
| ) | ||||
| 
 | ||||
| App( | ||||
|     appid="bt_settings", | ||||
|     name="Bluetooth", | ||||
|     apptype=FlipperAppType.SETTINGS, | ||||
|     entry_point="bt_settings_app", | ||||
|     stack_size=1 * 1024, | ||||
|     requires=[ | ||||
|         "bt", | ||||
|         "gui", | ||||
|     ], | ||||
|     order=10, | ||||
| ) | ||||
| 
 | ||||
| App( | ||||
|     appid="bt_debug", | ||||
|     name="Bluetooth Debug", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="bt_debug_app", | ||||
|     stack_size=1 * 1024, | ||||
|     requires=[ | ||||
|         "bt", | ||||
|         "gui", | ||||
|         "dialogs", | ||||
|     ], | ||||
|     order=110, | ||||
| ) | ||||
| 
 | ||||
| App( | ||||
|     appid="bt_hid", | ||||
|     name="Bluetooth Remote", | ||||
|     apptype=FlipperAppType.PLUGIN, | ||||
|     entry_point="bt_hid_app", | ||||
|     stack_size=1 * 1024, | ||||
|     cdefines=["APP_BLE_HID"], | ||||
|     requires=[ | ||||
|         "bt", | ||||
|         "gui", | ||||
|     ], | ||||
|     order=10, | ||||
| ) | ||||
| @ -7,4 +7,5 @@ App( | ||||
|     requires=["gui"], | ||||
|     stack_size=4 * 1024, | ||||
|     order=40, | ||||
|     fap_category="Debug", | ||||
| ) | ||||
							
								
								
									
										16
									
								
								applications/debug/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								applications/debug/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| App( | ||||
|     appid="debug_apps", | ||||
|     name="Basic debug apps bundle", | ||||
|     apptype=FlipperAppType.METAPACKAGE, | ||||
|     provides=[ | ||||
|         "blink_test", | ||||
|         "vibro_test", | ||||
|         "keypad_test", | ||||
|         "usb_test", | ||||
|         "usb_mouse", | ||||
|         "uart_echo", | ||||
|         "display_test", | ||||
|         "text_box_test", | ||||
|         "file_browser_test", | ||||
|     ], | ||||
| ) | ||||
							
								
								
									
										14
									
								
								applications/debug/battery_test_app/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								applications/debug/battery_test_app/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| App( | ||||
|     appid="battery_test", | ||||
|     name="Battery Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="battery_test_app", | ||||
|     cdefines=["APP_BATTERY_TEST"], | ||||
|     requires=[ | ||||
|         "gui", | ||||
|         "power", | ||||
|     ], | ||||
|     stack_size=1 * 1024, | ||||
|     order=130, | ||||
|     fap_category="Debug", | ||||
| ) | ||||
| @ -27,7 +27,7 @@ static void battery_test_battery_info_update_model(void* context) { | ||||
|         .charge = app->info.charge, | ||||
|         .health = app->info.health, | ||||
|     }; | ||||
|     battery_info_set_data(app->batery_info, &battery_info_data); | ||||
|     battery_info_set_data(app->battery_info, &battery_info_data); | ||||
|     notification_message(app->notifications, &sequence_display_backlight_on); | ||||
| } | ||||
| 
 | ||||
| @ -48,13 +48,13 @@ BatteryTestApp* battery_test_alloc() { | ||||
|     view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); | ||||
| 
 | ||||
|     // Views
 | ||||
|     app->batery_info = battery_info_alloc(); | ||||
|     app->battery_info = battery_info_alloc(); | ||||
|     view_set_previous_callback( | ||||
|         battery_info_get_view(app->batery_info), battery_test_exit_confirm_view); | ||||
|         battery_info_get_view(app->battery_info), battery_test_exit_confirm_view); | ||||
|     view_dispatcher_add_view( | ||||
|         app->view_dispatcher, | ||||
|         BatteryTestAppViewBatteryInfo, | ||||
|         battery_info_get_view(app->batery_info)); | ||||
|         battery_info_get_view(app->battery_info)); | ||||
| 
 | ||||
|     app->dialog = dialog_ex_alloc(); | ||||
|     dialog_ex_set_header(app->dialog, "Close Battery Test?", 64, 12, AlignCenter, AlignTop); | ||||
| @ -76,7 +76,7 @@ void battery_test_free(BatteryTestApp* app) { | ||||
| 
 | ||||
|     // Views
 | ||||
|     view_dispatcher_remove_view(app->view_dispatcher, BatteryTestAppViewBatteryInfo); | ||||
|     battery_info_free(app->batery_info); | ||||
|     battery_info_free(app->battery_info); | ||||
|     view_dispatcher_remove_view(app->view_dispatcher, BatteryTestAppViewExitDialog); | ||||
|     dialog_ex_free(app->dialog); | ||||
|     // View dispatcher
 | ||||
| @ -6,14 +6,15 @@ | ||||
| #include <notification/notification.h> | ||||
| 
 | ||||
| #include <gui/modules/dialog_ex.h> | ||||
| #include <power/power_settings_app/views/battery_info.h> | ||||
| // FIXME
 | ||||
| #include "../settings/power_settings_app/views/battery_info.h" | ||||
| 
 | ||||
| typedef struct { | ||||
|     Power* power; | ||||
|     Gui* gui; | ||||
|     NotificationApp* notifications; | ||||
|     ViewDispatcher* view_dispatcher; | ||||
|     BatteryInfo* batery_info; | ||||
|     BatteryInfo* battery_info; | ||||
|     DialogEx* dialog; | ||||
|     PowerInfo info; | ||||
| } BatteryTestApp; | ||||
							
								
								
									
										11
									
								
								applications/debug/blink_test/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								applications/debug/blink_test/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| App( | ||||
|     appid="blink_test", | ||||
|     name="Blink Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="blink_test_app", | ||||
|     cdefines=["APP_BLINK"], | ||||
|     requires=["gui"], | ||||
|     stack_size=1 * 1024, | ||||
|     order=10, | ||||
|     fap_category="Debug", | ||||
| ) | ||||
							
								
								
									
										18
									
								
								applications/debug/bt_debug_app/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								applications/debug/bt_debug_app/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| App( | ||||
|     appid="bt_debug", | ||||
|     name="Bluetooth Debug", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="bt_debug_app", | ||||
|     cdefines=["SRV_BT"], | ||||
|     requires=[ | ||||
|         "bt", | ||||
|         "gui", | ||||
|         "dialogs", | ||||
|     ], | ||||
|     provides=[ | ||||
|         "bt_debug", | ||||
|     ], | ||||
|     stack_size=1 * 1024, | ||||
|     order=110, | ||||
|     fap_category="Debug", | ||||
| ) | ||||
| @ -9,7 +9,7 @@ | ||||
| #include <gui/modules/submenu.h> | ||||
| #include "views/bt_carrier_test.h" | ||||
| #include "views/bt_packet_test.h" | ||||
| #include "../bt_settings.h" | ||||
| #include <bt/bt_settings.h> | ||||
| 
 | ||||
| typedef struct { | ||||
|     BtSettings settings; | ||||
							
								
								
									
										11
									
								
								applications/debug/display_test/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								applications/debug/display_test/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| App( | ||||
|     appid="display_test", | ||||
|     name="Display Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="display_test_app", | ||||
|     cdefines=["APP_DISPLAY_TEST"], | ||||
|     requires=["gui"], | ||||
|     stack_size=1 * 1024, | ||||
|     order=120, | ||||
|     fap_category="Debug", | ||||
| ) | ||||
							
								
								
									
										11
									
								
								applications/debug/file_browser_test/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								applications/debug/file_browser_test/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| App( | ||||
|     appid="file_browser_test", | ||||
|     name="File Browser Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="file_browser_app", | ||||
|     cdefines=["APP_FILE_BROWSER_TEST"], | ||||
|     requires=["gui"], | ||||
|     stack_size=2 * 1024, | ||||
|     order=150, | ||||
|     fap_category="Debug", | ||||
| ) | ||||
							
								
								
									
										11
									
								
								applications/debug/keypad_test/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								applications/debug/keypad_test/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| App( | ||||
|     appid="keypad_test", | ||||
|     name="Keypad Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="keypad_test_app", | ||||
|     cdefines=["APP_KEYPAD_TEST"], | ||||
|     requires=["gui"], | ||||
|     stack_size=1 * 1024, | ||||
|     order=30, | ||||
|     fap_category="Debug", | ||||
| ) | ||||
| @ -5,8 +5,11 @@ App( | ||||
|     entry_point="lfrfid_debug_app", | ||||
|     requires=[ | ||||
|         "gui", | ||||
|         "lfrfid", | ||||
|     ], | ||||
|     provides=[ | ||||
|         "lfrfid_debug", | ||||
|     ], | ||||
|     stack_size=1 * 1024, | ||||
|     order=100, | ||||
|     fap_category="Debug", | ||||
| ) | ||||
| @ -9,9 +9,8 @@ | ||||
| 
 | ||||
| #include <gui/modules/submenu.h> | ||||
| 
 | ||||
| #include <lfrfid_debug/views/lfrfid_debug_view_tune.h> | ||||
| 
 | ||||
| #include <lfrfid_debug/scenes/lfrfid_debug_scene.h> | ||||
| #include "views/lfrfid_debug_view_tune.h" | ||||
| #include "scenes/lfrfid_debug_scene.h" | ||||
| 
 | ||||
| typedef struct LfRfidDebug LfRfidDebug; | ||||
| 
 | ||||
							
								
								
									
										11
									
								
								applications/debug/text_box_test/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								applications/debug/text_box_test/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| App( | ||||
|     appid="text_box_test", | ||||
|     name="Text Box Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="text_box_test_app", | ||||
|     cdefines=["APP_TEXT_BOX_TEST"], | ||||
|     requires=["gui"], | ||||
|     stack_size=1 * 1024, | ||||
|     order=140, | ||||
|     fap_category="Debug", | ||||
| ) | ||||
							
								
								
									
										11
									
								
								applications/debug/uart_echo/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								applications/debug/uart_echo/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| App( | ||||
|     appid="uart_echo", | ||||
|     name="UART Echo", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="uart_echo_app", | ||||
|     cdefines=["APP_UART_ECHO"], | ||||
|     requires=["gui"], | ||||
|     stack_size=2 * 1024, | ||||
|     order=70, | ||||
|     fap_category="Debug", | ||||
| ) | ||||
| @ -10,7 +10,7 @@ App( | ||||
| App( | ||||
|     appid="delay_test", | ||||
|     name="Delay Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     apptype=FlipperAppType.SYSTEM, | ||||
|     entry_point="delay_test_app", | ||||
|     stack_size=1 * 1024, | ||||
|     requires=["unit_tests"], | ||||
| @ -1,6 +1,6 @@ | ||||
| #include <furi.h> | ||||
| #include <furi_hal.h> | ||||
| #include <applications/storage/storage.h> | ||||
| #include <storage/storage.h> | ||||
| #include <lib/flipper_format/flipper_format.h> | ||||
| #include <lib/nfc/protocols/nfca.h> | ||||
| #include <lib/digital_signal/digital_signal.h> | ||||
							
								
								
									
										11
									
								
								applications/debug/usb_mouse/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								applications/debug/usb_mouse/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| App( | ||||
|     appid="usb_mouse", | ||||
|     name="USB Mouse Demo", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="usb_mouse_app", | ||||
|     cdefines=["APP_USB_MOUSE"], | ||||
|     requires=["gui"], | ||||
|     stack_size=1 * 1024, | ||||
|     order=60, | ||||
|     fap_category="Debug", | ||||
| ) | ||||
							
								
								
									
										11
									
								
								applications/debug/usb_test/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								applications/debug/usb_test/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| App( | ||||
|     appid="usb_test", | ||||
|     name="USB Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="usb_test_app", | ||||
|     cdefines=["APP_USB_TEST"], | ||||
|     requires=["gui"], | ||||
|     stack_size=1 * 1024, | ||||
|     order=50, | ||||
|     fap_category="Debug", | ||||
| ) | ||||
							
								
								
									
										11
									
								
								applications/debug/vibro_test/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								applications/debug/vibro_test/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| App( | ||||
|     appid="vibro_test", | ||||
|     name="Vibro Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="vibro_test_app", | ||||
|     cdefines=["APP_VIBRO_TEST"], | ||||
|     requires=["gui"], | ||||
|     stack_size=1 * 1024, | ||||
|     order=20, | ||||
|     fap_category="Debug", | ||||
| ) | ||||
| @ -1,115 +0,0 @@ | ||||
| App( | ||||
|     appid="debug_apps", | ||||
|     name="Basic debug apps bundle", | ||||
|     apptype=FlipperAppType.METAPACKAGE, | ||||
|     provides=[ | ||||
|         "blink_test", | ||||
|         "vibro_test", | ||||
|         "keypad_test", | ||||
|         "usb_test", | ||||
|         "usb_mouse", | ||||
|         "uart_echo", | ||||
|         "display_test", | ||||
|         "text_box_test", | ||||
|         "file_browser_test", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| App( | ||||
|     appid="blink_test", | ||||
|     name="Blink Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="blink_test_app", | ||||
|     cdefines=["APP_BLINK"], | ||||
|     requires=["gui"], | ||||
|     stack_size=1 * 1024, | ||||
|     order=10, | ||||
| ) | ||||
| 
 | ||||
| App( | ||||
|     appid="vibro_test", | ||||
|     name="Vibro Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="vibro_test_app", | ||||
|     cdefines=["APP_VIBRO_TEST"], | ||||
|     requires=["gui"], | ||||
|     stack_size=1 * 1024, | ||||
|     order=20, | ||||
| ) | ||||
| 
 | ||||
| App( | ||||
|     appid="keypad_test", | ||||
|     name="Keypad Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="keypad_test_app", | ||||
|     cdefines=["APP_KEYPAD_TEST"], | ||||
|     requires=["gui"], | ||||
|     stack_size=1 * 1024, | ||||
|     order=30, | ||||
| ) | ||||
| 
 | ||||
| App( | ||||
|     appid="usb_test", | ||||
|     name="USB Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="usb_test_app", | ||||
|     cdefines=["APP_USB_TEST"], | ||||
|     requires=["gui"], | ||||
|     stack_size=1 * 1024, | ||||
|     order=50, | ||||
| ) | ||||
| 
 | ||||
| App( | ||||
|     appid="usb_mouse", | ||||
|     name="USB Mouse Demo", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="usb_mouse_app", | ||||
|     cdefines=["APP_USB_MOUSE"], | ||||
|     requires=["gui"], | ||||
|     stack_size=1 * 1024, | ||||
|     order=60, | ||||
| ) | ||||
| 
 | ||||
| App( | ||||
|     appid="uart_echo", | ||||
|     name="UART Echo", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="uart_echo_app", | ||||
|     cdefines=["APP_UART_ECHO"], | ||||
|     requires=["gui"], | ||||
|     stack_size=2 * 1024, | ||||
|     order=70, | ||||
| ) | ||||
| 
 | ||||
| App( | ||||
|     appid="display_test", | ||||
|     name="Display Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="display_test_app", | ||||
|     cdefines=["APP_DISPLAY_TEST"], | ||||
|     requires=["gui"], | ||||
|     stack_size=1 * 1024, | ||||
|     order=120, | ||||
| ) | ||||
| 
 | ||||
| App( | ||||
|     appid="text_box_test", | ||||
|     name="Text Box Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="text_box_test_app", | ||||
|     cdefines=["APP_TEXT_BOX_TEST"], | ||||
|     requires=["gui"], | ||||
|     stack_size=1 * 1024, | ||||
|     order=140, | ||||
| ) | ||||
| 
 | ||||
| App( | ||||
|     appid="file_browser_test", | ||||
|     name="File Browser Test", | ||||
|     apptype=FlipperAppType.DEBUG, | ||||
|     entry_point="file_browser_app", | ||||
|     cdefines=["APP_FILE_BROWSER_TEST"], | ||||
|     requires=["gui"], | ||||
|     stack_size=2 * 1024, | ||||
|     order=150, | ||||
| ) | ||||
| @ -1,58 +0,0 @@ | ||||
| Import("ENV") | ||||
| 
 | ||||
| 
 | ||||
| from fbt.appmanifest import FlipperAppType | ||||
| 
 | ||||
| appenv = ENV.Clone(tools=["fbt_extapps"]) | ||||
| 
 | ||||
| appenv.Replace( | ||||
|     LINKER_SCRIPT="application-ext", | ||||
|     STRIPFLAGS=[ | ||||
|         "--strip-debug", | ||||
|         "--strip-unneeded", | ||||
|         "-d", | ||||
|         "-g", | ||||
|         "-S", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| appenv.AppendUnique( | ||||
|     CCFLAGS=[ | ||||
|         "-Os", | ||||
|         "-ggdb3", | ||||
|         "-mword-relocations", | ||||
|         "-mlong-calls", | ||||
|         "-fno-common", | ||||
|         "-nostdlib", | ||||
|         "-fvisibility=hidden", | ||||
|     ], | ||||
|     LINKFLAGS=[ | ||||
|         "-r", | ||||
|         "-s", | ||||
|         # "-Bsymbolic", | ||||
|         "-nostartfiles", | ||||
|         "-mlong-calls", | ||||
|         "-fno-common", | ||||
|         "-nostdlib", | ||||
|         "-Wl,--gc-sections", | ||||
|         "-Wl,--no-export-dynamic", | ||||
|         "-fvisibility=hidden", | ||||
|         "-Wl,-e${APP_ENTRY}", | ||||
|         "-Xlinker", | ||||
|         "-Map=${TARGET}.map", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| extapps = [] | ||||
| for apptype in (FlipperAppType.PLUGIN, FlipperAppType.EXTERNAL): | ||||
|     for app in appenv["APPBUILD"].get_apps_of_type(apptype): | ||||
|         extapps.append(appenv.BuildAppElf(app)) | ||||
| 
 | ||||
| # Ugly access to global option | ||||
| if extra_app_list := GetOption("extra_ext_apps"): | ||||
|     for extra_app in extra_app_list.split(","): | ||||
|         extapps.append(appenv.BuildAppElf(appenv["APPMGR"].get(extra_app))) | ||||
| 
 | ||||
| Alias(appenv["FIRMWARE_BUILD_CFG"] + "_extapps", extapps) | ||||
| Return("extapps") | ||||
| @ -1,13 +0,0 @@ | ||||
| App( | ||||
|     appid="gui", | ||||
|     name="GuiSrv", | ||||
|     apptype=FlipperAppType.SERVICE, | ||||
|     entry_point="gui_srv", | ||||
|     cdefines=["SRV_GUI"], | ||||
|     requires=[ | ||||
|         "input", | ||||
|         "notification", | ||||
|     ], | ||||
|     stack_size=2 * 1024, | ||||
|     order=70, | ||||
| ) | ||||
| @ -1,131 +0,0 @@ | ||||
| #include "dialog.h" | ||||
| #include <gui/elements.h> | ||||
| #include <furi.h> | ||||
| 
 | ||||
| struct Dialog { | ||||
|     View* view; | ||||
|     void* context; | ||||
|     DialogResultCallback callback; | ||||
| }; | ||||
| 
 | ||||
| typedef struct { | ||||
|     const char* header_text; | ||||
|     const char* text; | ||||
|     const char* left_text; | ||||
|     const char* right_text; | ||||
| } DialogModel; | ||||
| 
 | ||||
| static void dialog_view_draw_callback(Canvas* canvas, void* _model) { | ||||
|     DialogModel* model = _model; | ||||
|     uint8_t canvas_center = canvas_width(canvas) / 2; | ||||
| 
 | ||||
|     // Prepare canvas
 | ||||
|     canvas_clear(canvas); | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
| 
 | ||||
|     // Draw header
 | ||||
|     canvas_set_font(canvas, FontPrimary); | ||||
|     canvas_draw_str_aligned( | ||||
|         canvas, canvas_center, 17, AlignCenter, AlignBottom, model->header_text); | ||||
| 
 | ||||
|     // Draw text
 | ||||
|     canvas_set_font(canvas, FontSecondary); | ||||
|     elements_multiline_text_aligned( | ||||
|         canvas, canvas_center, 32, AlignCenter, AlignCenter, model->text); | ||||
| 
 | ||||
|     // Draw buttons
 | ||||
|     elements_button_left(canvas, model->left_text); | ||||
|     elements_button_right(canvas, model->right_text); | ||||
| } | ||||
| 
 | ||||
| static bool dialog_view_input_callback(InputEvent* event, void* context) { | ||||
|     Dialog* dialog = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     // Process key presses only
 | ||||
|     if(event->type == InputTypeShort && dialog->callback) { | ||||
|         if(event->key == InputKeyLeft) { | ||||
|             dialog->callback(DialogResultLeft, dialog->context); | ||||
|             consumed = true; | ||||
|         } else if(event->key == InputKeyRight) { | ||||
|             dialog->callback(DialogResultRight, dialog->context); | ||||
|             consumed = true; | ||||
|         } else if(event->key == InputKeyBack) { | ||||
|             dialog->callback(DialogResultBack, dialog->context); | ||||
|             consumed = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| Dialog* dialog_alloc() { | ||||
|     Dialog* dialog = malloc(sizeof(Dialog)); | ||||
|     dialog->view = view_alloc(); | ||||
|     view_set_context(dialog->view, dialog); | ||||
|     view_allocate_model(dialog->view, ViewModelTypeLockFree, sizeof(DialogModel)); | ||||
|     view_set_draw_callback(dialog->view, dialog_view_draw_callback); | ||||
|     view_set_input_callback(dialog->view, dialog_view_input_callback); | ||||
|     return dialog; | ||||
| } | ||||
| 
 | ||||
| void dialog_free(Dialog* dialog) { | ||||
|     furi_assert(dialog); | ||||
|     view_free(dialog->view); | ||||
|     free(dialog); | ||||
| } | ||||
| 
 | ||||
| View* dialog_get_view(Dialog* dialog) { | ||||
|     furi_assert(dialog); | ||||
|     return dialog->view; | ||||
| } | ||||
| 
 | ||||
| void dialog_set_result_callback(Dialog* dialog, DialogResultCallback callback) { | ||||
|     furi_assert(dialog); | ||||
|     dialog->callback = callback; | ||||
| } | ||||
| 
 | ||||
| void dialog_set_context(Dialog* dialog, void* context) { | ||||
|     furi_assert(dialog); | ||||
|     dialog->context = context; | ||||
| } | ||||
| 
 | ||||
| void dialog_set_header_text(Dialog* dialog, const char* text) { | ||||
|     furi_assert(dialog); | ||||
|     furi_assert(text); | ||||
|     with_view_model( | ||||
|         dialog->view, (DialogModel * model) { | ||||
|             model->header_text = text; | ||||
|             return true; | ||||
|         }); | ||||
| } | ||||
| 
 | ||||
| void dialog_set_text(Dialog* dialog, const char* text) { | ||||
|     furi_assert(dialog); | ||||
|     furi_assert(text); | ||||
|     with_view_model( | ||||
|         dialog->view, (DialogModel * model) { | ||||
|             model->text = text; | ||||
|             return true; | ||||
|         }); | ||||
| } | ||||
| 
 | ||||
| void dialog_set_left_button_text(Dialog* dialog, const char* text) { | ||||
|     furi_assert(dialog); | ||||
|     furi_assert(text); | ||||
|     with_view_model( | ||||
|         dialog->view, (DialogModel * model) { | ||||
|             model->left_text = text; | ||||
|             return true; | ||||
|         }); | ||||
| } | ||||
| 
 | ||||
| void dialog_set_right_button_text(Dialog* dialog, const char* text) { | ||||
|     furi_assert(dialog); | ||||
|     furi_assert(text); | ||||
|     with_view_model( | ||||
|         dialog->view, (DialogModel * model) { | ||||
|             model->right_text = text; | ||||
|             return true; | ||||
|         }); | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 SG
						SG