[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:
SG 2022-09-15 02:11:38 +10:00 committed by Aleksandr Kutuzov
parent 0f6f9ad52e
commit b9a766d909
895 changed files with 8862 additions and 1465 deletions

View File

@ -1,86 +1,191 @@
---
Language: Cpp
AccessModifierOffset: -4 AccessModifierOffset: -4
AlignAfterOpenBracket: AlwaysBreak AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: false AlignArrayOfStructures: None
AlignConsecutiveDeclarations: false AlignConsecutiveMacros: None
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: Left AlignEscapedNewlines: Left
AlignOperands: true AlignOperands: Align
AlignTrailingComments: false AlignTrailingComments: false
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false AllowAllParametersOfDeclarationOnNextLine: false
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Never AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: true AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false AlwaysBreakTemplateDeclarations: Yes
AttributeMacros:
- __capability
BinPackArguments: false BinPackArguments: false
BinPackParameters: 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 BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: true
BreakBeforeBraces: Attach BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: false BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: false BreakStringLiterals: false
ColumnLimit: 99 ColumnLimit: 99
CommentPragmas: '^ IWYU pragma:'
QualifierAlignment: Leave
CompactNamespaces: false CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4 ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4 ContinuationIndentWidth: 4
Cpp11BracedListStyle: true Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false DerivePointerAlignment: false
DisableFormat: false DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false ExperimentalAutoDetectBinPacking: false
PackConstructorInitializers: BinPack
BasedOnStyle: ''
ConstructorInitializerAllOnOneLineOrOnePerLine: false
AllowAllConstructorInitializersOnNextLine: true
FixNamespaceComments: false FixNamespaceComments: false
ForEachMacros:
IncludeBlocks: Preserve - foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories: IncludeCategories:
- Regex: '.*' - Regex: '.*'
Priority: 1 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)?$' IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseLabels: false IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None IndentPPDirectives: None
IndentWidth: 4 IndentExternBlock: AfterExternBlock
IndentRequires: false
IndentWidth: 4
IndentWrappedFunctionNames: true IndentWrappedFunctionNames: true
InsertTrailingCommas: None
JavaScriptQuotes: Leave JavaScriptQuotes: Leave
JavaScriptWrapImports: true JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false KeepEmptyLinesAtTheStartOfBlocks: false
LambdaBodyIndentation: Signature
MacroBlockBegin: '' MacroBlockBegin: ''
MacroBlockEnd: '' MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 1
NamespaceIndentation: None NamespaceIndentation: None
ObjCBinPackProtocolList: Auto ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4 ObjCBlockIndentWidth: 4
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: true ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true ObjCSpaceBeforeProtocolList: true
# Taken from git's rules
PenaltyBreakAssignment: 10 PenaltyBreakAssignment: 10
PenaltyBreakBeforeFirstCallParameter: 30 PenaltyBreakBeforeFirstCallParameter: 30
PenaltyBreakComment: 10 PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0 PenaltyBreakFirstLessLess: 0
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 10 PenaltyBreakString: 10
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 100 PenaltyExcessCharacter: 100
PenaltyReturnTypeOnItsOwnLine: 60 PenaltyReturnTypeOnItsOwnLine: 60
PenaltyIndentedWhitespace: 0
PointerAlignment: Left PointerAlignment: Left
ReflowComments: false PPIndentWidth: -1
SortIncludes: false ReferenceAlignment: Pointer
ReflowComments: false
RemoveBracesLLVM: false
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: Never
SortJavaStaticImport: Before
SortUsingDeclarations: false SortUsingDeclarations: false
SpaceAfterCStyleCast: false SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true SpaceBeforeInheritanceColon: true
SpaceBeforeParens: Never SpaceBeforeParens: Never
SpaceBeforeParensOptions:
AfterControlStatements: false
AfterForeachMacros: false
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: false
AfterOverloadedOperator: false
BeforeNonEmptyParentheses: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1 SpacesBeforeTrailingComments: 1
SpacesInAngles: false SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false SpacesInParentheses: false
SpacesInSquareBrackets: false SpacesInSquareBrackets: false
Standard: Cpp03 SpaceBeforeSquareBrackets: false
TabWidth: 4 BitFieldColonSpacing: Both
UseTab: Never 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
View File

@ -28,3 +28,6 @@
[submodule "lib/mbedtls"] [submodule "lib/mbedtls"]
path = lib/mbedtls path = lib/mbedtls
url = https://github.com/Mbed-TLS/mbedtls.git url = https://github.com/Mbed-TLS/mbedtls.git
[submodule "lib/cxxheaderparser"]
path = lib/cxxheaderparser
url = https://github.com/robotpy/cxxheaderparser.git

View File

@ -31,7 +31,10 @@
], ],
"postAttachCommands": [ "postAttachCommands": [
// "attach 1", // "attach 1",
"compare-sections", // "compare-sections",
"source debug/flipperapps.py",
// "source debug/FreeRTOS/FreeRTOS.py",
// "svd_load debug/STM32WB55_CM4.svd"
] ]
// "showDevDebugOutput": "raw", // "showDevDebugOutput": "raw",
}, },
@ -50,7 +53,8 @@
"attach 1", "attach 1",
"set confirm off", "set confirm off",
"set mem inaccessible-by-default off", "set mem inaccessible-by-default off",
"compare-sections", "source debug/flipperapps.py",
// "compare-sections",
] ]
// "showDevDebugOutput": "raw", // "showDevDebugOutput": "raw",
}, },
@ -65,6 +69,9 @@
"device": "STM32WB55RG", "device": "STM32WB55RG",
"svdFile": "./debug/STM32WB55_CM4.svd", "svdFile": "./debug/STM32WB55_CM4.svd",
"rtos": "FreeRTOS", "rtos": "FreeRTOS",
"postAttachCommands": [
"source debug/flipperapps.py",
]
// "showDevDebugOutput": "raw", // "showDevDebugOutput": "raw",
}, },
{ {
@ -73,7 +80,7 @@
"request": "launch", "request": "launch",
"program": "./lib/scons/scripts/scons.py", "program": "./lib/scons/scripts/scons.py",
"args": [ "args": [
"sdk" "plugin_dist"
] ]
}, },
{ {

View File

@ -12,6 +12,9 @@
"cortex-debug.openocdPath.windows": "${workspaceFolder}/toolchain/i686-windows/openocd/bin/openocd.exe", "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.linux": "${workspaceFolder}/toolchain/x86_64-linux/openocd/bin/openocd",
"cortex-debug.openocdPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/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, "editor.formatOnSave": true,
"files.associations": { "files.associations": {
"*.scons": "python", "*.scons": "python",

View File

@ -93,11 +93,41 @@
"type": "shell", "type": "shell",
"command": "./fbt FIRMWARE_APP_SET=unit_tests FORCE=1 flash_usb" "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)", "label": "[Release] Flash (USB, with resources)",
"group": "build", "group": "build",
"type": "shell", "type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb_full" "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}"
}
] ]
} }

View File

@ -14,6 +14,10 @@ You should clone with
$ git clone --recursive https://github.com/flipperdevices/flipperzero-firmware.git $ 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 # Update firmware
[Get Latest Firmware from Update Server](https://update.flipperzero.one/) [Get Latest Firmware from Update Server](https://update.flipperzero.one/)

View File

@ -9,9 +9,10 @@
import os import os
import subprocess import subprocess
DefaultEnvironment(tools=[])
EnsurePythonVersion(3, 8) EnsurePythonVersion(3, 8)
DefaultEnvironment(tools=[])
# Progress(["OwO\r", "owo\r", "uwu\r", "owo\r"], interval=15) # Progress(["OwO\r", "owo\r", "uwu\r", "owo\r"], interval=15)
@ -58,6 +59,8 @@ distenv = coreenv.Clone(
"-ex", "-ex",
"source debug/FreeRTOS/FreeRTOS.py", "source debug/FreeRTOS/FreeRTOS.py",
"-ex", "-ex",
"source debug/flipperapps.py",
"-ex",
"source debug/PyCortexMDebug/PyCortexMDebug.py", "source debug/PyCortexMDebug/PyCortexMDebug.py",
"-ex", "-ex",
"svd_load ${SVD_FILE}", "svd_load ${SVD_FILE}",
@ -160,6 +163,28 @@ if GetOption("fullenv") or any(
basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"]) basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"])
distenv.Default(basic_dist) 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 # Target for bundling core2 package for qFlipper
copro_dist = distenv.CoproBuilder( copro_dist = distenv.CoproBuilder(
distenv.Dir("assets/core2_firmware"), distenv.Dir("assets/core2_firmware"),
@ -240,7 +265,6 @@ firmware_env.Append(
"site_scons", "site_scons",
"scripts", "scripts",
# Extra files # Extra files
"applications/extapps.scons",
"SConstruct", "SConstruct",
"firmware.scons", "firmware.scons",
"fbt_options.py", "fbt_options.py",

View File

@ -1,38 +1,90 @@
# Structure # Structure
- `about` - Small About application that shows flipper info - `application.h` - Firmware application list header
- `accessor` - Wiegand server
## 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 - `archive` - Archive and file manager
- `bad_usb` - Bad USB application - `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 - `bt` - BLE service and application
- `cli` - Console service and API - `cli` - Console service and API
- `crypto` - Crypto cli tools - `crypto` - Crypto cli tools
- `debug_tools` - Different tools that we use for debug
- `desktop` - Desktop service - `desktop` - Desktop service
- `dialogs` - Dialogs service: GUI Dialogs for your app - `dialogs` - Dialogs service: GUI Dialogs for your app
- `dolphin` - Dolphin service and supplementary apps - `dolphin` - Dolphin service and supplementary apps
- `gpio` - GPIO application: includes USART bridge and GPIO control
- `gui` - GUI service and API - `gui` - GUI service and API
- `ibutton` - iButton application, onewire keys and more
- `input` - Input service - `input` - Input service
- `infrared` - Infrared application, controls your IR devices
- `lfrfid` - LF RFID application
- `lfrfid_debug` - LF RFID debug tool
- `loader` - Application loader service - `loader` - Application loader service
- `music_player` - Music player app (demo)
- `nfc` - NFC application, HF rfid, EMV and etc
- `notification` - Notification service - `notification` - Notification service
- `power` - Power service - `power` - Power service
- `power_observer` - Power debug tool
- `rpc` - RPC service and API - `rpc` - RPC service and API
- `scened_app_example` - C++ application example
- `snake_game` - Snake game application
- `storage` - Storage service, internal + sdcard - `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

View File

@ -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,
)

View File

@ -7,4 +7,5 @@ App(
requires=["gui"], requires=["gui"],
stack_size=4 * 1024, stack_size=4 * 1024,
order=40, order=40,
fap_category="Debug",
) )

View 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",
],
)

View 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",
)

View File

@ -27,7 +27,7 @@ static void battery_test_battery_info_update_model(void* context) {
.charge = app->info.charge, .charge = app->info.charge,
.health = app->info.health, .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); 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); view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
// Views // Views
app->batery_info = battery_info_alloc(); app->battery_info = battery_info_alloc();
view_set_previous_callback( 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( view_dispatcher_add_view(
app->view_dispatcher, app->view_dispatcher,
BatteryTestAppViewBatteryInfo, BatteryTestAppViewBatteryInfo,
battery_info_get_view(app->batery_info)); battery_info_get_view(app->battery_info));
app->dialog = dialog_ex_alloc(); app->dialog = dialog_ex_alloc();
dialog_ex_set_header(app->dialog, "Close Battery Test?", 64, 12, AlignCenter, AlignTop); dialog_ex_set_header(app->dialog, "Close Battery Test?", 64, 12, AlignCenter, AlignTop);
@ -76,7 +76,7 @@ void battery_test_free(BatteryTestApp* app) {
// Views // Views
view_dispatcher_remove_view(app->view_dispatcher, BatteryTestAppViewBatteryInfo); 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); view_dispatcher_remove_view(app->view_dispatcher, BatteryTestAppViewExitDialog);
dialog_ex_free(app->dialog); dialog_ex_free(app->dialog);
// View dispatcher // View dispatcher

View File

@ -6,14 +6,15 @@
#include <notification/notification.h> #include <notification/notification.h>
#include <gui/modules/dialog_ex.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 { typedef struct {
Power* power; Power* power;
Gui* gui; Gui* gui;
NotificationApp* notifications; NotificationApp* notifications;
ViewDispatcher* view_dispatcher; ViewDispatcher* view_dispatcher;
BatteryInfo* batery_info; BatteryInfo* battery_info;
DialogEx* dialog; DialogEx* dialog;
PowerInfo info; PowerInfo info;
} BatteryTestApp; } BatteryTestApp;

View 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",
)

View 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",
)

View File

@ -9,7 +9,7 @@
#include <gui/modules/submenu.h> #include <gui/modules/submenu.h>
#include "views/bt_carrier_test.h" #include "views/bt_carrier_test.h"
#include "views/bt_packet_test.h" #include "views/bt_packet_test.h"
#include "../bt_settings.h" #include <bt/bt_settings.h>
typedef struct { typedef struct {
BtSettings settings; BtSettings settings;

View 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",
)

View 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",
)

View 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",
)

View File

@ -5,8 +5,11 @@ App(
entry_point="lfrfid_debug_app", entry_point="lfrfid_debug_app",
requires=[ requires=[
"gui", "gui",
"lfrfid", ],
provides=[
"lfrfid_debug",
], ],
stack_size=1 * 1024, stack_size=1 * 1024,
order=100, order=100,
fap_category="Debug",
) )

View File

@ -9,9 +9,8 @@
#include <gui/modules/submenu.h> #include <gui/modules/submenu.h>
#include <lfrfid_debug/views/lfrfid_debug_view_tune.h> #include "views/lfrfid_debug_view_tune.h"
#include "scenes/lfrfid_debug_scene.h"
#include <lfrfid_debug/scenes/lfrfid_debug_scene.h>
typedef struct LfRfidDebug LfRfidDebug; typedef struct LfRfidDebug LfRfidDebug;

View 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",
)

View 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",
)

View File

@ -10,7 +10,7 @@ App(
App( App(
appid="delay_test", appid="delay_test",
name="Delay Test", name="Delay Test",
apptype=FlipperAppType.DEBUG, apptype=FlipperAppType.SYSTEM,
entry_point="delay_test_app", entry_point="delay_test_app",
stack_size=1 * 1024, stack_size=1 * 1024,
requires=["unit_tests"], requires=["unit_tests"],

View File

@ -1,6 +1,6 @@
#include <furi.h> #include <furi.h>
#include <furi_hal.h> #include <furi_hal.h>
#include <applications/storage/storage.h> #include <storage/storage.h>
#include <lib/flipper_format/flipper_format.h> #include <lib/flipper_format/flipper_format.h>
#include <lib/nfc/protocols/nfca.h> #include <lib/nfc/protocols/nfca.h>
#include <lib/digital_signal/digital_signal.h> #include <lib/digital_signal/digital_signal.h>

View 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",
)

View 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",
)

View 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",
)

View File

@ -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,
)

View File

@ -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")

View File

@ -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,
)

View File

@ -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