diff --git a/.clang-format b/.clang-format index 3337a740..4b76f7fa 100644 --- a/.clang-format +++ b/.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 +ColumnLimit: 99 +CommentPragmas: '^ IWYU pragma:' +QualifierAlignment: Leave CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true +DeriveLineEnding: true DerivePointerAlignment: false -DisableFormat: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock ExperimentalAutoDetectBinPacking: false +PackConstructorInitializers: BinPack +BasedOnStyle: '' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllConstructorInitializersOnNextLine: true FixNamespaceComments: false - -IncludeBlocks: Preserve +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve IncludeCategories: - - Regex: '.*' - Priority: 1 + - 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 -IndentWidth: 4 +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 4 IndentWrappedFunctionNames: true +InsertTrailingCommas: None JavaScriptQuotes: Leave JavaScriptWrapImports: true KeepEmptyLinesAtTheStartOfBlocks: false +LambdaBodyIndentation: Signature MacroBlockBegin: '' -MacroBlockEnd: '' +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 -ReflowComments: false -SortIncludes: false +PPIndentWidth: -1 +ReferenceAlignment: Pointer +ReflowComments: 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 -TabWidth: 4 -UseTab: Never +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 +... + diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6dac0496..c9b8ff3f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,82 +2,58 @@ * @skotopes @DrZlo13 @hedger # Apps -/applications/about/ @skotopes @DrZlo13 @hedger -/applications/accessor/ @skotopes @DrZlo13 @hedger -/applications/archive/ @skotopes @DrZlo13 @hedger @nminaylov -/applications/bad_usb/ @skotopes @DrZlo13 @hedger @nminaylov -/applications/bt/ @skotopes @DrZlo13 @hedger @gornekich -/applications/cli/ @skotopes @DrZlo13 @hedger @nminaylov -/applications/crypto/ @skotopes @DrZlo13 @hedger @nminaylov -/applications/debug_tools/ @skotopes @DrZlo13 @hedger -/applications/desktop/ @skotopes @DrZlo13 @hedger @nminaylov -/applications/dialogs/ @skotopes @DrZlo13 @hedger -/applications/dolphin/ @skotopes @DrZlo13 @hedger -/applications/gpio/ @skotopes @DrZlo13 @hedger @nminaylov -/applications/gui/ @skotopes @DrZlo13 @hedger -/applications/ibutton/ @skotopes @DrZlo13 @hedger @gsurkov -/applications/infrared/ @skotopes @DrZlo13 @hedger @gsurkov -/applications/input/ @skotopes @DrZlo13 @hedger -/applications/lfrfid/ @skotopes @DrZlo13 @hedger -/applications/lfrfid_debug/ @skotopes @DrZlo13 @hedger -/applications/loader/ @skotopes @DrZlo13 @hedger -/applications/music_player/ @skotopes @DrZlo13 @hedger -/applications/nfc/ @skotopes @DrZlo13 @hedger @gornekich -/applications/notification/ @skotopes @DrZlo13 @hedger -/applications/power/ @skotopes @DrZlo13 @hedger -/applications/rpc/ @skotopes @DrZlo13 @hedger @nminaylov -/applications/snake_game/ @skotopes @DrZlo13 @hedger -/applications/storage/ @skotopes @DrZlo13 @hedger -/applications/storage_settings/ @skotopes @DrZlo13 @hedger -/applications/subghz/ @skotopes @DrZlo13 @hedger @Skorpionm -/applications/system/ @skotopes @DrZlo13 @hedger -/applications/u2f/ @skotopes @DrZlo13 @hedger @nminaylov -/applications/unit_tests/ @skotopes @DrZlo13 @hedger -/applications/updater/ @skotopes @DrZlo13 @hedger +/applications/debug/bt_debug_app/ @skotopes @DrZlo13 @hedger @gornekich +/applications/debug/accessor/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/debug/battery_test_app/ @skotopes @DrZlo13 @hedger @gornekich +/applications/debug/bt_debug_app/ @skotopes @DrZlo13 @hedger @gornekich +/applications/debug/file_browser_test/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/debug/lfrfid_debug/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/debug/text_box_test/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/debug/uart_echo/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/debug/usb_mouse/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/debug/usb_test/ @skotopes @DrZlo13 @hedger @nminaylov -# Assets -/assets/ @skotopes @DrZlo13 @hedger +/applications/main/archive/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/main/bad_usb/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/main/gpio/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/main/ibutton/ @skotopes @DrZlo13 @hedger @gsurkov +/applications/main/infrared/ @skotopes @DrZlo13 @hedger @gsurkov +/applications/main/nfc/ @skotopes @DrZlo13 @hedger @gornekich +/applications/main/subghz/ @skotopes @DrZlo13 @hedger @Skorpionm +/applications/main/u2f/ @skotopes @DrZlo13 @hedger @nminaylov -# Furi Core -/furi/ @skotopes @DrZlo13 @hedger +/applications/plugins/bt_hid_app/ @skotopes @DrZlo13 @hedger @gornekich +/applications/plugins/picopass/ @skotopes @DrZlo13 @hedger @gornekich -# Debug tools and plugins -/debug/ @skotopes @DrZlo13 @hedger +/applications/services/bt/ @skotopes @DrZlo13 @hedger @gornekich +/applications/services/cli/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/services/crypto/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/services/desktop/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/services/dolphin/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/services/power/ @skotopes @DrZlo13 @hedger @gornekich +/applications/services/rpc/ @skotopes @DrZlo13 @hedger @nminaylov + +/applications/services/bt_settings_app/ @skotopes @DrZlo13 @hedger @gornekich +/applications/services/desktop_settings/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/services/dolphin_passport/ @skotopes @DrZlo13 @hedger @nminaylov +/applications/services/power_settings_app/ @skotopes @DrZlo13 @hedger @gornekich + +/applications/system/storage_move_to_sd/ @skotopes @DrZlo13 @hedger @nminaylov # Documentation /documentation/ @skotopes @DrZlo13 @hedger @drunkbatya - -# Firmware targets -/firmware/ @skotopes @DrZlo13 @hedger +/scripts/toolchain/ @skotopes @DrZlo13 @hedger @drunkbatya # Lib -/lib/FreeRTOS-Kernel/ @skotopes @DrZlo13 @hedger -/lib/FreeRTOS-glue/ @skotopes @DrZlo13 @hedger /lib/ST25RFAL002/ @skotopes @DrZlo13 @hedger @gornekich /lib/STM32CubeWB/ @skotopes @DrZlo13 @hedger @gornekich -/lib/app-scened-template/ @skotopes @DrZlo13 @hedger -/lib/callback-connector/ @skotopes @DrZlo13 @hedger /lib/digital_signal/ @skotopes @DrZlo13 @hedger @gornekich -/lib/drivers/ @skotopes @DrZlo13 @hedger -/lib/fatfs/ @skotopes @DrZlo13 @hedger -/lib/flipper_format/ @skotopes @DrZlo13 @hedger -/lib/fnv1a-hash/ @skotopes @DrZlo13 @hedger -/lib/heatshrink/ @skotopes @DrZlo13 @hedger /lib/infrared/ @skotopes @DrZlo13 @hedger @gsurkov +/lib/lfrfid/ @skotopes @DrZlo13 @hedger @nminaylov /lib/libusb_stm32/ @skotopes @DrZlo13 @hedger @nminaylov -/lib/littlefs/ @skotopes @DrZlo13 @hedger -/lib/lfs_config.h @skotopes @DrZlo13 @hedger +/lib/mbedtls/ @skotopes @DrZlo13 @hedger @nminaylov /lib/micro-ecc/ @skotopes @DrZlo13 @hedger @nminaylov -/lib/microtar/ @skotopes @DrZlo13 @hedger -/lib/mlib/ @skotopes @DrZlo13 @hedger -/lib/nanopb/ @skotopes @DrZlo13 @hedger +/lib/nanopb/ @skotopes @DrZlo13 @hedger @nminaylov /lib/nfc/ @skotopes @DrZlo13 @hedger @gornekich -/lib/one_wire/ @skotopes @DrZlo13 @hedger -/lib/qrcode/ @skotopes @DrZlo13 @hedger +/lib/one_wire/ @skotopes @DrZlo13 @hedger @gsurkov /lib/subghz/ @skotopes @DrZlo13 @hedger @Skorpionm -/lib/toolbox/ @skotopes @DrZlo13 @hedger -/lib/u8g2/ @skotopes @DrZlo13 @hedger -/lib/update_util/ @skotopes @DrZlo13 @hedger - -# Helper scripts -/scripts/ @skotopes @DrZlo13 @hedger diff --git a/.gitmodules b/.gitmodules index b580a8c7..ba764498 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/.vscode/example/launch.json b/.vscode/example/launch.json index bdad0428..7cb2542d 100644 --- a/.vscode/example/launch.json +++ b/.vscode/example/launch.json @@ -9,6 +9,10 @@ "type": "command", "command": "shellCommand.execute", "args": { + "useSingleResult": true, + "env": { + "PATH": "${workspaceFolder};${env:PATH}" + }, "command": "./fbt get_blackmagic", "description": "Get Blackmagic device", } @@ -31,7 +35,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 +57,8 @@ "attach 1", "set confirm off", "set mem inaccessible-by-default off", - "compare-sections", + "source debug/flipperapps.py", + // "compare-sections", ] // "showDevDebugOutput": "raw", }, @@ -65,6 +73,9 @@ "device": "STM32WB55RG", "svdFile": "./debug/STM32WB55_CM4.svd", "rtos": "FreeRTOS", + "postAttachCommands": [ + "source debug/flipperapps.py", + ] // "showDevDebugOutput": "raw", }, { @@ -73,7 +84,7 @@ "request": "launch", "program": "./lib/scons/scripts/scons.py", "args": [ - "sdk" + "plugin_dist" ] }, { diff --git a/.vscode/example/settings.json b/.vscode/example/settings.json index 925c2e07..d84707e0 100644 --- a/.vscode/example/settings.json +++ b/.vscode/example/settings.json @@ -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-py", "editor.formatOnSave": true, "files.associations": { "*.scons": "python", @@ -19,4 +22,4 @@ "SConstruct": "python", "*.fam": "python", } -} \ No newline at end of file +} diff --git a/.vscode/example/tasks.json b/.vscode/example/tasks.json index 32efa006..3946d05c 100644 --- a/.vscode/example/tasks.json +++ b/.vscode/example/tasks.json @@ -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}" + } ] } \ No newline at end of file diff --git a/ReadMe.md b/ReadMe.md index 2e3b87a6..e848e18a 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -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/) diff --git a/SConstruct b/SConstruct index 4462f2f3..5ad2ac3c 100644 --- a/SConstruct +++ b/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) @@ -43,6 +44,8 @@ distenv = coreenv.Clone( "target extended-remote ${GDBREMOTE}", "-ex", "set confirm off", + "-ex", + "set pagination off", ], GDBOPTS_BLACKMAGIC=[ "-ex", @@ -58,6 +61,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 +165,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"), @@ -209,10 +236,19 @@ distenv.PhonyTarget( distenv.PhonyTarget( "debug_other", "${GDBPYCOM}", - GDBPYOPTS='-ex "source debug/PyCortexMDebug/PyCortexMDebug.py" ', + GDBOPTS="${GDBOPTS_BASE}", GDBREMOTE="${OPENOCD_GDB_PIPE}", + GDBPYOPTS='-ex "source debug/PyCortexMDebug/PyCortexMDebug.py" ', ) +distenv.PhonyTarget( + "debug_other_blackmagic", + "${GDBPYCOM}", + GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}", + GDBREMOTE="$${BLACKMAGIC_ADDR}", +) + + # Just start OpenOCD distenv.PhonyTarget( "openocd", @@ -240,7 +276,6 @@ firmware_env.Append( "site_scons", "scripts", # Extra files - "applications/extapps.scons", "SConstruct", "firmware.scons", "fbt_options.py", diff --git a/applications/ReadMe.md b/applications/ReadMe.md index cb2f5628..6224cb45 100644 --- a/applications/ReadMe.md +++ b/applications/ReadMe.md @@ -1,38 +1,89 @@ # Structure -- `about` - Small About application that shows flipper info -- `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 - `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. + +- `applications.h` - Firmware application list header + - `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 diff --git a/applications/bt/application.fam b/applications/bt/application.fam deleted file mode 100644 index 248386ff..00000000 --- a/applications/bt/application.fam +++ /dev/null @@ -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, -) diff --git a/applications/accessor/accessor.cpp b/applications/debug/accessor/accessor.cpp similarity index 100% rename from applications/accessor/accessor.cpp rename to applications/debug/accessor/accessor.cpp diff --git a/applications/accessor/accessor_app.cpp b/applications/debug/accessor/accessor_app.cpp similarity index 100% rename from applications/accessor/accessor_app.cpp rename to applications/debug/accessor/accessor_app.cpp diff --git a/applications/accessor/accessor_app.h b/applications/debug/accessor/accessor_app.h similarity index 100% rename from applications/accessor/accessor_app.h rename to applications/debug/accessor/accessor_app.h diff --git a/applications/accessor/accessor_event.h b/applications/debug/accessor/accessor_event.h similarity index 100% rename from applications/accessor/accessor_event.h rename to applications/debug/accessor/accessor_event.h diff --git a/applications/accessor/accessor_view_manager.cpp b/applications/debug/accessor/accessor_view_manager.cpp similarity index 100% rename from applications/accessor/accessor_view_manager.cpp rename to applications/debug/accessor/accessor_view_manager.cpp diff --git a/applications/accessor/accessor_view_manager.h b/applications/debug/accessor/accessor_view_manager.h similarity index 100% rename from applications/accessor/accessor_view_manager.h rename to applications/debug/accessor/accessor_view_manager.h diff --git a/applications/accessor/application.fam b/applications/debug/accessor/application.fam similarity index 88% rename from applications/accessor/application.fam rename to applications/debug/accessor/application.fam index 8a94049e..93fc9bc3 100644 --- a/applications/accessor/application.fam +++ b/applications/debug/accessor/application.fam @@ -7,4 +7,5 @@ App( requires=["gui"], stack_size=4 * 1024, order=40, + fap_category="Debug", ) diff --git a/applications/accessor/helpers/wiegand.cpp b/applications/debug/accessor/helpers/wiegand.cpp similarity index 100% rename from applications/accessor/helpers/wiegand.cpp rename to applications/debug/accessor/helpers/wiegand.cpp diff --git a/applications/accessor/helpers/wiegand.h b/applications/debug/accessor/helpers/wiegand.h similarity index 100% rename from applications/accessor/helpers/wiegand.h rename to applications/debug/accessor/helpers/wiegand.h diff --git a/applications/accessor/scene/accessor_scene_generic.h b/applications/debug/accessor/scene/accessor_scene_generic.h similarity index 100% rename from applications/accessor/scene/accessor_scene_generic.h rename to applications/debug/accessor/scene/accessor_scene_generic.h diff --git a/applications/accessor/scene/accessor_scene_start.cpp b/applications/debug/accessor/scene/accessor_scene_start.cpp similarity index 100% rename from applications/accessor/scene/accessor_scene_start.cpp rename to applications/debug/accessor/scene/accessor_scene_start.cpp diff --git a/applications/accessor/scene/accessor_scene_start.h b/applications/debug/accessor/scene/accessor_scene_start.h similarity index 100% rename from applications/accessor/scene/accessor_scene_start.h rename to applications/debug/accessor/scene/accessor_scene_start.h diff --git a/applications/debug/application.fam b/applications/debug/application.fam new file mode 100644 index 00000000..a33b3693 --- /dev/null +++ b/applications/debug/application.fam @@ -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", + ], +) diff --git a/applications/debug/battery_test_app/application.fam b/applications/debug/battery_test_app/application.fam new file mode 100644 index 00000000..b388445c --- /dev/null +++ b/applications/debug/battery_test_app/application.fam @@ -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", +) diff --git a/applications/power/battery_test_app/battery_test_app.c b/applications/debug/battery_test_app/battery_test_app.c similarity index 92% rename from applications/power/battery_test_app/battery_test_app.c rename to applications/debug/battery_test_app/battery_test_app.c index ab6889dc..eabf3c04 100644 --- a/applications/power/battery_test_app/battery_test_app.c +++ b/applications/debug/battery_test_app/battery_test_app.c @@ -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 diff --git a/applications/power/battery_test_app/battery_test_app.h b/applications/debug/battery_test_app/battery_test_app.h similarity index 82% rename from applications/power/battery_test_app/battery_test_app.h rename to applications/debug/battery_test_app/battery_test_app.h index 9c17626d..497cdde8 100644 --- a/applications/power/battery_test_app/battery_test_app.h +++ b/applications/debug/battery_test_app/battery_test_app.h @@ -6,14 +6,15 @@ #include #include -#include +// 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; diff --git a/applications/debug/blink_test/application.fam b/applications/debug/blink_test/application.fam new file mode 100644 index 00000000..c6a8a922 --- /dev/null +++ b/applications/debug/blink_test/application.fam @@ -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", +) diff --git a/applications/debug_tools/blink_test.c b/applications/debug/blink_test/blink_test.c similarity index 100% rename from applications/debug_tools/blink_test.c rename to applications/debug/blink_test/blink_test.c diff --git a/applications/debug/bt_debug_app/application.fam b/applications/debug/bt_debug_app/application.fam new file mode 100644 index 00000000..8ed1ccc0 --- /dev/null +++ b/applications/debug/bt_debug_app/application.fam @@ -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", +) diff --git a/applications/bt/bt_debug_app/bt_debug_app.c b/applications/debug/bt_debug_app/bt_debug_app.c similarity index 100% rename from applications/bt/bt_debug_app/bt_debug_app.c rename to applications/debug/bt_debug_app/bt_debug_app.c diff --git a/applications/bt/bt_debug_app/bt_debug_app.h b/applications/debug/bt_debug_app/bt_debug_app.h similarity index 95% rename from applications/bt/bt_debug_app/bt_debug_app.h rename to applications/debug/bt_debug_app/bt_debug_app.h index c3657626..cd59e4d0 100644 --- a/applications/bt/bt_debug_app/bt_debug_app.h +++ b/applications/debug/bt_debug_app/bt_debug_app.h @@ -9,7 +9,7 @@ #include #include "views/bt_carrier_test.h" #include "views/bt_packet_test.h" -#include "../bt_settings.h" +#include typedef struct { BtSettings settings; diff --git a/applications/bt/bt_debug_app/views/bt_carrier_test.c b/applications/debug/bt_debug_app/views/bt_carrier_test.c similarity index 100% rename from applications/bt/bt_debug_app/views/bt_carrier_test.c rename to applications/debug/bt_debug_app/views/bt_carrier_test.c diff --git a/applications/bt/bt_debug_app/views/bt_carrier_test.h b/applications/debug/bt_debug_app/views/bt_carrier_test.h similarity index 100% rename from applications/bt/bt_debug_app/views/bt_carrier_test.h rename to applications/debug/bt_debug_app/views/bt_carrier_test.h diff --git a/applications/bt/bt_debug_app/views/bt_packet_test.c b/applications/debug/bt_debug_app/views/bt_packet_test.c similarity index 100% rename from applications/bt/bt_debug_app/views/bt_packet_test.c rename to applications/debug/bt_debug_app/views/bt_packet_test.c diff --git a/applications/bt/bt_debug_app/views/bt_packet_test.h b/applications/debug/bt_debug_app/views/bt_packet_test.h similarity index 100% rename from applications/bt/bt_debug_app/views/bt_packet_test.h rename to applications/debug/bt_debug_app/views/bt_packet_test.h diff --git a/applications/bt/bt_debug_app/views/bt_test.c b/applications/debug/bt_debug_app/views/bt_test.c similarity index 100% rename from applications/bt/bt_debug_app/views/bt_test.c rename to applications/debug/bt_debug_app/views/bt_test.c diff --git a/applications/bt/bt_debug_app/views/bt_test.h b/applications/debug/bt_debug_app/views/bt_test.h similarity index 100% rename from applications/bt/bt_debug_app/views/bt_test.h rename to applications/debug/bt_debug_app/views/bt_test.h diff --git a/applications/bt/bt_debug_app/views/bt_test_types.h b/applications/debug/bt_debug_app/views/bt_test_types.h similarity index 100% rename from applications/bt/bt_debug_app/views/bt_test_types.h rename to applications/debug/bt_debug_app/views/bt_test_types.h diff --git a/applications/debug/display_test/application.fam b/applications/debug/display_test/application.fam new file mode 100644 index 00000000..4b40322f --- /dev/null +++ b/applications/debug/display_test/application.fam @@ -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", +) diff --git a/applications/debug_tools/display_test/display_test.c b/applications/debug/display_test/display_test.c similarity index 100% rename from applications/debug_tools/display_test/display_test.c rename to applications/debug/display_test/display_test.c diff --git a/applications/debug_tools/display_test/display_test.h b/applications/debug/display_test/display_test.h similarity index 100% rename from applications/debug_tools/display_test/display_test.h rename to applications/debug/display_test/display_test.h diff --git a/applications/debug_tools/display_test/view_display_test.c b/applications/debug/display_test/view_display_test.c similarity index 100% rename from applications/debug_tools/display_test/view_display_test.c rename to applications/debug/display_test/view_display_test.c diff --git a/applications/debug_tools/display_test/view_display_test.h b/applications/debug/display_test/view_display_test.h similarity index 100% rename from applications/debug_tools/display_test/view_display_test.h rename to applications/debug/display_test/view_display_test.h diff --git a/applications/debug/file_browser_test/application.fam b/applications/debug/file_browser_test/application.fam new file mode 100644 index 00000000..5e4c7f46 --- /dev/null +++ b/applications/debug/file_browser_test/application.fam @@ -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", +) diff --git a/applications/debug_tools/file_browser_test/file_browser_app.c b/applications/debug/file_browser_test/file_browser_app.c similarity index 100% rename from applications/debug_tools/file_browser_test/file_browser_app.c rename to applications/debug/file_browser_test/file_browser_app.c diff --git a/applications/debug_tools/file_browser_test/file_browser_app_i.h b/applications/debug/file_browser_test/file_browser_app_i.h similarity index 100% rename from applications/debug_tools/file_browser_test/file_browser_app_i.h rename to applications/debug/file_browser_test/file_browser_app_i.h diff --git a/applications/debug_tools/file_browser_test/scenes/file_browser_scene.c b/applications/debug/file_browser_test/scenes/file_browser_scene.c similarity index 100% rename from applications/debug_tools/file_browser_test/scenes/file_browser_scene.c rename to applications/debug/file_browser_test/scenes/file_browser_scene.c diff --git a/applications/debug_tools/file_browser_test/scenes/file_browser_scene.h b/applications/debug/file_browser_test/scenes/file_browser_scene.h similarity index 100% rename from applications/debug_tools/file_browser_test/scenes/file_browser_scene.h rename to applications/debug/file_browser_test/scenes/file_browser_scene.h diff --git a/applications/debug_tools/file_browser_test/scenes/file_browser_scene_browser.c b/applications/debug/file_browser_test/scenes/file_browser_scene_browser.c similarity index 100% rename from applications/debug_tools/file_browser_test/scenes/file_browser_scene_browser.c rename to applications/debug/file_browser_test/scenes/file_browser_scene_browser.c diff --git a/applications/debug_tools/file_browser_test/scenes/file_browser_scene_config.h b/applications/debug/file_browser_test/scenes/file_browser_scene_config.h similarity index 100% rename from applications/debug_tools/file_browser_test/scenes/file_browser_scene_config.h rename to applications/debug/file_browser_test/scenes/file_browser_scene_config.h diff --git a/applications/debug_tools/file_browser_test/scenes/file_browser_scene_result.c b/applications/debug/file_browser_test/scenes/file_browser_scene_result.c similarity index 100% rename from applications/debug_tools/file_browser_test/scenes/file_browser_scene_result.c rename to applications/debug/file_browser_test/scenes/file_browser_scene_result.c diff --git a/applications/debug_tools/file_browser_test/scenes/file_browser_scene_start.c b/applications/debug/file_browser_test/scenes/file_browser_scene_start.c similarity index 100% rename from applications/debug_tools/file_browser_test/scenes/file_browser_scene_start.c rename to applications/debug/file_browser_test/scenes/file_browser_scene_start.c diff --git a/applications/debug/keypad_test/application.fam b/applications/debug/keypad_test/application.fam new file mode 100644 index 00000000..6859af26 --- /dev/null +++ b/applications/debug/keypad_test/application.fam @@ -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", +) diff --git a/applications/debug_tools/keypad_test.c b/applications/debug/keypad_test/keypad_test.c similarity index 100% rename from applications/debug_tools/keypad_test.c rename to applications/debug/keypad_test/keypad_test.c diff --git a/applications/lfrfid_debug/application.fam b/applications/debug/lfrfid_debug/application.fam similarity index 74% rename from applications/lfrfid_debug/application.fam rename to applications/debug/lfrfid_debug/application.fam index 910f65cf..6844f929 100644 --- a/applications/lfrfid_debug/application.fam +++ b/applications/debug/lfrfid_debug/application.fam @@ -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", ) diff --git a/applications/debug/lfrfid_debug/lfrfid_debug.c b/applications/debug/lfrfid_debug/lfrfid_debug.c new file mode 100644 index 00000000..63d66b68 --- /dev/null +++ b/applications/debug/lfrfid_debug/lfrfid_debug.c @@ -0,0 +1,81 @@ +#include "lfrfid_debug_i.h" + +static bool lfrfid_debug_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + LfRfidDebug* app = context; + return scene_manager_handle_custom_event(app->scene_manager, event); +} + +static bool lfrfid_debug_back_event_callback(void* context) { + furi_assert(context); + LfRfidDebug* app = context; + return scene_manager_handle_back_event(app->scene_manager); +} + +static LfRfidDebug* lfrfid_debug_alloc() { + LfRfidDebug* app = malloc(sizeof(LfRfidDebug)); + + app->view_dispatcher = view_dispatcher_alloc(); + app->scene_manager = scene_manager_alloc(&lfrfid_debug_scene_handlers, app); + view_dispatcher_enable_queue(app->view_dispatcher); + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + view_dispatcher_set_custom_event_callback( + app->view_dispatcher, lfrfid_debug_custom_event_callback); + view_dispatcher_set_navigation_event_callback( + app->view_dispatcher, lfrfid_debug_back_event_callback); + + // Open GUI record + app->gui = furi_record_open(RECORD_GUI); + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + // Submenu + app->submenu = submenu_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, LfRfidDebugViewSubmenu, submenu_get_view(app->submenu)); + + // Tune view + app->tune_view = lfrfid_debug_view_tune_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + LfRfidDebugViewTune, + lfrfid_debug_view_tune_get_view(app->tune_view)); + + return app; +} + +static void lfrfid_debug_free(LfRfidDebug* app) { + furi_assert(app); + + // Submenu + view_dispatcher_remove_view(app->view_dispatcher, LfRfidDebugViewSubmenu); + submenu_free(app->submenu); + + // Tune view + view_dispatcher_remove_view(app->view_dispatcher, LfRfidDebugViewTune); + lfrfid_debug_view_tune_free(app->tune_view); + + // View Dispatcher + view_dispatcher_free(app->view_dispatcher); + + // Scene Manager + scene_manager_free(app->scene_manager); + + // GUI + furi_record_close(RECORD_GUI); + app->gui = NULL; + + free(app); +} + +int32_t lfrfid_debug_app(void* p) { + UNUSED(p); + LfRfidDebug* app = lfrfid_debug_alloc(); + + scene_manager_next_scene(app->scene_manager, LfRfidDebugSceneStart); + + view_dispatcher_run(app->view_dispatcher); + + lfrfid_debug_free(app); + + return 0; +} \ No newline at end of file diff --git a/applications/debug/lfrfid_debug/lfrfid_debug_i.h b/applications/debug/lfrfid_debug/lfrfid_debug_i.h new file mode 100644 index 00000000..8e4e7238 --- /dev/null +++ b/applications/debug/lfrfid_debug/lfrfid_debug_i.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include + +#include +#include +#include +#include + +#include + +#include "views/lfrfid_debug_view_tune.h" +#include "scenes/lfrfid_debug_scene.h" + +typedef struct LfRfidDebug LfRfidDebug; + +struct LfRfidDebug { + Gui* gui; + ViewDispatcher* view_dispatcher; + SceneManager* scene_manager; + + // Common Views + Submenu* submenu; + LfRfidTuneView* tune_view; +}; + +typedef enum { + LfRfidDebugViewSubmenu, + LfRfidDebugViewTune, +} LfRfidDebugView; diff --git a/applications/debug/lfrfid_debug/scenes/lfrfid_debug_app_scene_start.c b/applications/debug/lfrfid_debug/scenes/lfrfid_debug_app_scene_start.c new file mode 100644 index 00000000..2fc6706e --- /dev/null +++ b/applications/debug/lfrfid_debug/scenes/lfrfid_debug_app_scene_start.c @@ -0,0 +1,44 @@ +#include "../lfrfid_debug_i.h" + +typedef enum { + SubmenuIndexTune, +} SubmenuIndex; + +static void lfrfid_debug_scene_start_submenu_callback(void* context, uint32_t index) { + LfRfidDebug* app = context; + + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +void lfrfid_debug_scene_start_on_enter(void* context) { + LfRfidDebug* app = context; + Submenu* submenu = app->submenu; + + submenu_add_item( + submenu, "Tune", SubmenuIndexTune, lfrfid_debug_scene_start_submenu_callback, app); + + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidDebugSceneStart)); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidDebugViewSubmenu); +} + +bool lfrfid_debug_scene_start_on_event(void* context, SceneManagerEvent event) { + LfRfidDebug* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexTune) { + scene_manager_next_scene(app->scene_manager, LfRfidDebugSceneTune); + consumed = true; + } + } + + return consumed; +} + +void lfrfid_debug_scene_start_on_exit(void* context) { + LfRfidDebug* app = context; + + submenu_reset(app->submenu); +} diff --git a/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.cpp b/applications/debug/lfrfid_debug/scenes/lfrfid_debug_app_scene_tune.c similarity index 53% rename from applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.cpp rename to applications/debug/lfrfid_debug/scenes/lfrfid_debug_app_scene_tune.c index 4b627649..c7f3bf24 100644 --- a/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.cpp +++ b/applications/debug/lfrfid_debug/scenes/lfrfid_debug_app_scene_tune.c @@ -1,4 +1,4 @@ -#include "lfrfid_debug_app_scene_tune.h" +#include "../lfrfid_debug_i.h" #include static void comparator_trigger_callback(bool level, void* comp_ctx) { @@ -6,32 +6,38 @@ static void comparator_trigger_callback(bool level, void* comp_ctx) { furi_hal_gpio_write(&gpio_ext_pa7, !level); } -void LfRfidDebugAppSceneTune::on_enter(LfRfidDebugApp* app, bool /* need_restore */) { - app->view_controller.switch_to(); +void lfrfid_debug_scene_tune_on_enter(void* context) { + LfRfidDebug* app = context; + furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull); - furi_hal_rfid_comp_set_callback(comparator_trigger_callback, this); + furi_hal_rfid_comp_set_callback(comparator_trigger_callback, app); furi_hal_rfid_comp_start(); furi_hal_rfid_pins_read(); furi_hal_rfid_tim_read(125000, 0.5); furi_hal_rfid_tim_read_start(); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidDebugViewTune); } -bool LfRfidDebugAppSceneTune::on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* /* event */) { +bool lfrfid_debug_scene_tune_on_event(void* context, SceneManagerEvent event) { + UNUSED(event); + + LfRfidDebug* app = context; bool consumed = false; - LfRfidViewTuneVM* tune = app->view_controller; - - if(tune->is_dirty()) { - furi_hal_rfid_set_read_period(tune->get_ARR()); - furi_hal_rfid_set_read_pulse(tune->get_CCR()); + if(lfrfid_debug_view_tune_is_dirty(app->tune_view)) { + furi_hal_rfid_set_read_period(lfrfid_debug_view_tune_get_arr(app->tune_view)); + furi_hal_rfid_set_read_pulse(lfrfid_debug_view_tune_get_ccr(app->tune_view)); } return consumed; } -void LfRfidDebugAppSceneTune::on_exit(LfRfidDebugApp* /* app */) { +void lfrfid_debug_scene_tune_on_exit(void* context) { + UNUSED(context); + furi_hal_rfid_comp_stop(); furi_hal_rfid_comp_set_callback(NULL, NULL); diff --git a/applications/debug/lfrfid_debug/scenes/lfrfid_debug_scene.c b/applications/debug/lfrfid_debug/scenes/lfrfid_debug_scene.c new file mode 100644 index 00000000..e6288e92 --- /dev/null +++ b/applications/debug/lfrfid_debug/scenes/lfrfid_debug_scene.c @@ -0,0 +1,30 @@ +#include "lfrfid_debug_scene.h" + +// Generate scene on_enter handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const lfrfid_debug_on_enter_handlers[])(void*) = { +#include "lfrfid_debug_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const lfrfid_debug_on_event_handlers[])(void* context, SceneManagerEvent event) = { +#include "lfrfid_debug_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const lfrfid_debug_on_exit_handlers[])(void* context) = { +#include "lfrfid_debug_scene_config.h" +}; +#undef ADD_SCENE + +// Initialize scene handlers configuration structure +const SceneManagerHandlers lfrfid_debug_scene_handlers = { + .on_enter_handlers = lfrfid_debug_on_enter_handlers, + .on_event_handlers = lfrfid_debug_on_event_handlers, + .on_exit_handlers = lfrfid_debug_on_exit_handlers, + .scene_num = LfRfidDebugSceneNum, +}; diff --git a/applications/debug/lfrfid_debug/scenes/lfrfid_debug_scene.h b/applications/debug/lfrfid_debug/scenes/lfrfid_debug_scene.h new file mode 100644 index 00000000..8fc74f72 --- /dev/null +++ b/applications/debug/lfrfid_debug/scenes/lfrfid_debug_scene.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +// Generate scene id and total number +#define ADD_SCENE(prefix, name, id) LfRfidDebugScene##id, +typedef enum { +#include "lfrfid_debug_scene_config.h" + LfRfidDebugSceneNum, +} LfRfidDebugScene; +#undef ADD_SCENE + +extern const SceneManagerHandlers lfrfid_debug_scene_handlers; + +// Generate scene on_enter handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); +#include "lfrfid_debug_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_event handlers declaration +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "lfrfid_debug_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_exit handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); +#include "lfrfid_debug_scene_config.h" +#undef ADD_SCENE diff --git a/applications/debug/lfrfid_debug/scenes/lfrfid_debug_scene_config.h b/applications/debug/lfrfid_debug/scenes/lfrfid_debug_scene_config.h new file mode 100644 index 00000000..f3cca47b --- /dev/null +++ b/applications/debug/lfrfid_debug/scenes/lfrfid_debug_scene_config.h @@ -0,0 +1,2 @@ +ADD_SCENE(lfrfid_debug, start, Start) +ADD_SCENE(lfrfid_debug, tune, Tune) diff --git a/applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.c b/applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.c new file mode 100644 index 00000000..38fe3603 --- /dev/null +++ b/applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.c @@ -0,0 +1,229 @@ +#include "lfrfid_debug_view_tune.h" +#include + +#define TEMP_STR_LEN 128 + +struct LfRfidTuneView { + View* view; +}; + +typedef struct { + bool dirty; + bool fine; + uint32_t ARR; + uint32_t CCR; + int pos; +} LfRfidTuneViewModel; + +static void lfrfid_debug_view_tune_draw_callback(Canvas* canvas, void* _model) { + LfRfidTuneViewModel* model = _model; + canvas_set_color(canvas, ColorBlack); + + if(model->fine) { + canvas_draw_box( + canvas, + 128 - canvas_string_width(canvas, "Fine") - 4, + 0, + canvas_string_width(canvas, "Fine") + 4, + canvas_current_font_height(canvas) + 1); + canvas_set_color(canvas, ColorWhite); + } + canvas_draw_str_aligned(canvas, 128 - 2, 2, AlignRight, AlignTop, "Fine"); + canvas_set_color(canvas, ColorBlack); + + char buffer[TEMP_STR_LEN + 1]; + double freq = ((float)SystemCoreClock / ((float)model->ARR + 1)); + double duty = ((float)model->CCR + 1) / ((float)model->ARR + 1) * 100.0f; + snprintf( + buffer, + TEMP_STR_LEN, + "%sARR: %lu\n" + "freq = %.4f\n" + "%sCCR: %lu\n" + "duty = %.4f", + model->pos == 0 ? ">" : "", + model->ARR, + freq, + model->pos == 1 ? ">" : "", + model->CCR, + duty); + elements_multiline_text_aligned(canvas, 2, 2, AlignLeft, AlignTop, buffer); +} + +static void lfrfid_debug_view_tune_button_up(LfRfidTuneView* tune_view) { + with_view_model( + tune_view->view, (LfRfidTuneViewModel * model) { + if(model->pos > 0) model->pos--; + return true; + }); +} + +static void lfrfid_debug_view_tune_button_down(LfRfidTuneView* tune_view) { + with_view_model( + tune_view->view, (LfRfidTuneViewModel * model) { + if(model->pos < 1) model->pos++; + return true; + }); +} + +static void lfrfid_debug_view_tune_button_left(LfRfidTuneView* tune_view) { + with_view_model( + tune_view->view, (LfRfidTuneViewModel * model) { + if(model->pos == 0) { + if(model->fine) { + model->ARR -= 1; + } else { + model->ARR -= 10; + } + } else if(model->pos == 1) { + if(model->fine) { + model->CCR -= 1; + } else { + model->CCR -= 10; + } + } + + model->dirty = true; + return true; + }); +} + +static void lfrfid_debug_view_tune_button_right(LfRfidTuneView* tune_view) { + with_view_model( + tune_view->view, (LfRfidTuneViewModel * model) { + if(model->pos == 0) { + if(model->fine) { + model->ARR += 1; + } else { + model->ARR += 10; + } + } else if(model->pos == 1) { + if(model->fine) { + model->CCR += 1; + } else { + model->CCR += 10; + } + } + + model->dirty = true; + return true; + }); +} + +static void lfrfid_debug_view_tune_button_ok(LfRfidTuneView* tune_view) { + with_view_model( + tune_view->view, (LfRfidTuneViewModel * model) { + model->fine = !model->fine; + return true; + }); +} + +static bool lfrfid_debug_view_tune_input_callback(InputEvent* event, void* context) { + LfRfidTuneView* tune_view = context; + bool consumed = false; + + // Process key presses only + if(event->type == InputTypeShort || event->type == InputTypeRepeat) { + consumed = true; + + switch(event->key) { + case InputKeyLeft: + lfrfid_debug_view_tune_button_left(tune_view); + break; + case InputKeyRight: + lfrfid_debug_view_tune_button_right(tune_view); + break; + case InputKeyUp: + lfrfid_debug_view_tune_button_up(tune_view); + break; + case InputKeyDown: + lfrfid_debug_view_tune_button_down(tune_view); + break; + case InputKeyOk: + lfrfid_debug_view_tune_button_ok(tune_view); + break; + default: + consumed = false; + break; + } + } + + return consumed; +} + +LfRfidTuneView* lfrfid_debug_view_tune_alloc() { + LfRfidTuneView* tune_view = malloc(sizeof(LfRfidTuneView)); + tune_view->view = view_alloc(); + view_set_context(tune_view->view, tune_view); + view_allocate_model(tune_view->view, ViewModelTypeLocking, sizeof(LfRfidTuneViewModel)); + + with_view_model( + tune_view->view, (LfRfidTuneViewModel * model) { + model->dirty = true; + model->fine = false; + model->ARR = 511; + model->CCR = 255; + model->pos = 0; + return true; + }); + + view_set_draw_callback(tune_view->view, lfrfid_debug_view_tune_draw_callback); + view_set_input_callback(tune_view->view, lfrfid_debug_view_tune_input_callback); + + return tune_view; +} + +void lfrfid_debug_view_tune_free(LfRfidTuneView* tune_view) { + view_free(tune_view->view); + free(tune_view); +} + +View* lfrfid_debug_view_tune_get_view(LfRfidTuneView* tune_view) { + return tune_view->view; +} + +void lfrfid_debug_view_tune_clean(LfRfidTuneView* tune_view) { + with_view_model( + tune_view->view, (LfRfidTuneViewModel * model) { + model->dirty = true; + model->fine = false; + model->ARR = 511; + model->CCR = 255; + model->pos = 0; + return true; + }); +} + +bool lfrfid_debug_view_tune_is_dirty(LfRfidTuneView* tune_view) { + bool result = false; + with_view_model( + tune_view->view, (LfRfidTuneViewModel * model) { + result = model->dirty; + model->dirty = false; + return false; + }); + + return result; +} + +uint32_t lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view) { + uint32_t result = false; + with_view_model( + tune_view->view, (LfRfidTuneViewModel * model) { + result = model->ARR; + return false; + }); + + return result; +} + +uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view) { + uint32_t result = false; + with_view_model( + tune_view->view, (LfRfidTuneViewModel * model) { + result = model->CCR; + return false; + }); + + return result; +} diff --git a/applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.h b/applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.h new file mode 100644 index 00000000..fd6d0b1f --- /dev/null +++ b/applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.h @@ -0,0 +1,18 @@ +#pragma once +#include + +typedef struct LfRfidTuneView LfRfidTuneView; + +LfRfidTuneView* lfrfid_debug_view_tune_alloc(); + +void lfrfid_debug_view_tune_free(LfRfidTuneView* tune_view); + +View* lfrfid_debug_view_tune_get_view(LfRfidTuneView* tune_view); + +void lfrfid_debug_view_tune_clean(LfRfidTuneView* tune_view); + +bool lfrfid_debug_view_tune_is_dirty(LfRfidTuneView* tune_view); + +uint32_t lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view); + +uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view); diff --git a/applications/debug/text_box_test/application.fam b/applications/debug/text_box_test/application.fam new file mode 100644 index 00000000..3e54df9c --- /dev/null +++ b/applications/debug/text_box_test/application.fam @@ -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", +) diff --git a/applications/debug_tools/text_box_test.c b/applications/debug/text_box_test/text_box_test.c similarity index 100% rename from applications/debug_tools/text_box_test.c rename to applications/debug/text_box_test/text_box_test.c diff --git a/applications/debug/uart_echo/application.fam b/applications/debug/uart_echo/application.fam new file mode 100644 index 00000000..8863a1a9 --- /dev/null +++ b/applications/debug/uart_echo/application.fam @@ -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", +) diff --git a/applications/debug_tools/uart_echo.c b/applications/debug/uart_echo/uart_echo.c similarity index 100% rename from applications/debug_tools/uart_echo.c rename to applications/debug/uart_echo/uart_echo.c diff --git a/applications/unit_tests/application.fam b/applications/debug/unit_tests/application.fam similarity index 90% rename from applications/unit_tests/application.fam rename to applications/debug/unit_tests/application.fam index 54e6feae..949bb3fc 100644 --- a/applications/unit_tests/application.fam +++ b/applications/debug/unit_tests/application.fam @@ -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"], diff --git a/applications/unit_tests/flipper_format/flipper_format_string_test.c b/applications/debug/unit_tests/flipper_format/flipper_format_string_test.c similarity index 100% rename from applications/unit_tests/flipper_format/flipper_format_string_test.c rename to applications/debug/unit_tests/flipper_format/flipper_format_string_test.c diff --git a/applications/unit_tests/flipper_format/flipper_format_test.c b/applications/debug/unit_tests/flipper_format/flipper_format_test.c similarity index 100% rename from applications/unit_tests/flipper_format/flipper_format_test.c rename to applications/debug/unit_tests/flipper_format/flipper_format_test.c diff --git a/applications/unit_tests/furi/furi_memmgr_test.c b/applications/debug/unit_tests/furi/furi_memmgr_test.c similarity index 100% rename from applications/unit_tests/furi/furi_memmgr_test.c rename to applications/debug/unit_tests/furi/furi_memmgr_test.c diff --git a/applications/unit_tests/furi/furi_pubsub_test.c b/applications/debug/unit_tests/furi/furi_pubsub_test.c similarity index 100% rename from applications/unit_tests/furi/furi_pubsub_test.c rename to applications/debug/unit_tests/furi/furi_pubsub_test.c diff --git a/applications/unit_tests/furi/furi_record_test.c b/applications/debug/unit_tests/furi/furi_record_test.c similarity index 100% rename from applications/unit_tests/furi/furi_record_test.c rename to applications/debug/unit_tests/furi/furi_record_test.c diff --git a/applications/unit_tests/furi/furi_test.c b/applications/debug/unit_tests/furi/furi_test.c similarity index 100% rename from applications/unit_tests/furi/furi_test.c rename to applications/debug/unit_tests/furi/furi_test.c diff --git a/applications/unit_tests/furi/furi_valuemutex_test.c b/applications/debug/unit_tests/furi/furi_valuemutex_test.c similarity index 100% rename from applications/unit_tests/furi/furi_valuemutex_test.c rename to applications/debug/unit_tests/furi/furi_valuemutex_test.c diff --git a/applications/unit_tests/infrared/infrared_test.c b/applications/debug/unit_tests/infrared/infrared_test.c similarity index 100% rename from applications/unit_tests/infrared/infrared_test.c rename to applications/debug/unit_tests/infrared/infrared_test.c diff --git a/applications/unit_tests/lfrfid/bit_lib_test.c b/applications/debug/unit_tests/lfrfid/bit_lib_test.c similarity index 100% rename from applications/unit_tests/lfrfid/bit_lib_test.c rename to applications/debug/unit_tests/lfrfid/bit_lib_test.c diff --git a/applications/unit_tests/lfrfid/lfrfid_protocols.c b/applications/debug/unit_tests/lfrfid/lfrfid_protocols.c similarity index 100% rename from applications/unit_tests/lfrfid/lfrfid_protocols.c rename to applications/debug/unit_tests/lfrfid/lfrfid_protocols.c diff --git a/applications/unit_tests/minunit.h b/applications/debug/unit_tests/minunit.h similarity index 100% rename from applications/unit_tests/minunit.h rename to applications/debug/unit_tests/minunit.h diff --git a/applications/unit_tests/minunit_vars.h b/applications/debug/unit_tests/minunit_vars.h similarity index 100% rename from applications/unit_tests/minunit_vars.h rename to applications/debug/unit_tests/minunit_vars.h diff --git a/applications/unit_tests/minunit_vars_ex.h b/applications/debug/unit_tests/minunit_vars_ex.h similarity index 100% rename from applications/unit_tests/minunit_vars_ex.h rename to applications/debug/unit_tests/minunit_vars_ex.h diff --git a/applications/unit_tests/nfc/nfc_test.c b/applications/debug/unit_tests/nfc/nfc_test.c similarity index 76% rename from applications/unit_tests/nfc/nfc_test.c rename to applications/debug/unit_tests/nfc/nfc_test.c index dcd162d1..580943f2 100644 --- a/applications/unit_tests/nfc/nfc_test.c +++ b/applications/debug/unit_tests/nfc/nfc_test.c @@ -1,8 +1,9 @@ #include #include -#include +#include #include #include +#include #include #include @@ -170,10 +171,59 @@ MU_TEST(nfc_digital_signal_test) { "NFC long digital signal test failed\r\n"); } +MU_TEST(mf_classic_dict_test) { + MfClassicDict* instance = NULL; + uint64_t key = 0; + string_t temp_str; + string_init(temp_str); + + instance = mf_classic_dict_alloc(MfClassicDictTypeUnitTest); + mu_assert(instance != NULL, "mf_classic_dict_alloc\r\n"); + + mu_assert( + mf_classic_dict_get_total_keys(instance) == 0, + "mf_classic_dict_get_total_keys == 0 assert failed\r\n"); + + string_set(temp_str, "2196FAD8115B"); + mu_assert( + mf_classic_dict_add_key_str(instance, temp_str), + "mf_classic_dict_add_key == true assert failed\r\n"); + + mu_assert( + mf_classic_dict_get_total_keys(instance) == 1, + "mf_classic_dict_get_total_keys == 1 assert failed\r\n"); + + mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n"); + + mu_assert( + mf_classic_dict_get_key_at_index_str(instance, temp_str, 0), + "mf_classic_dict_get_key_at_index_str == true assert failed\r\n"); + mu_assert( + string_cmp(temp_str, "2196FAD8115B") == 0, + "string_cmp(temp_str, \"2196FAD8115B\") == 0 assert failed\r\n"); + + mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n"); + + mu_assert( + mf_classic_dict_get_key_at_index(instance, &key, 0), + "mf_classic_dict_get_key_at_index == true assert failed\r\n"); + mu_assert(key == 0x2196FAD8115B, "key == 0x2196FAD8115B assert failed\r\n"); + + mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n"); + + mu_assert( + mf_classic_dict_delete_index(instance, 0), + "mf_classic_dict_delete_index == true assert failed\r\n"); + + mf_classic_dict_free(instance); + string_clear(temp_str); +} + MU_TEST_SUITE(nfc) { nfc_test_alloc(); MU_RUN_TEST(nfc_digital_signal_test); + MU_RUN_TEST(mf_classic_dict_test); nfc_test_free(); } diff --git a/applications/unit_tests/protocol_dict/protocol_dict_test.c b/applications/debug/unit_tests/protocol_dict/protocol_dict_test.c similarity index 100% rename from applications/unit_tests/protocol_dict/protocol_dict_test.c rename to applications/debug/unit_tests/protocol_dict/protocol_dict_test.c diff --git a/applications/unit_tests/rpc/rpc_test.c b/applications/debug/unit_tests/rpc/rpc_test.c similarity index 100% rename from applications/unit_tests/rpc/rpc_test.c rename to applications/debug/unit_tests/rpc/rpc_test.c diff --git a/applications/unit_tests/storage/dirwalk_test.c b/applications/debug/unit_tests/storage/dirwalk_test.c similarity index 100% rename from applications/unit_tests/storage/dirwalk_test.c rename to applications/debug/unit_tests/storage/dirwalk_test.c diff --git a/applications/unit_tests/storage/storage_test.c b/applications/debug/unit_tests/storage/storage_test.c similarity index 100% rename from applications/unit_tests/storage/storage_test.c rename to applications/debug/unit_tests/storage/storage_test.c diff --git a/applications/unit_tests/stream/stream_test.c b/applications/debug/unit_tests/stream/stream_test.c similarity index 100% rename from applications/unit_tests/stream/stream_test.c rename to applications/debug/unit_tests/stream/stream_test.c diff --git a/applications/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c similarity index 98% rename from applications/unit_tests/subghz/subghz_test.c rename to applications/debug/unit_tests/subghz/subghz_test.c index df269ed0..36f5b94c 100644 --- a/applications/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -13,7 +13,7 @@ #define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo") #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s") #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub") -#define TEST_RANDOM_COUNT_PARSE 232 +#define TEST_RANDOM_COUNT_PARSE 233 #define TEST_TIMEOUT 10000 static SubGhzEnvironment* environment_handler; @@ -434,6 +434,13 @@ MU_TEST(subghz_decoder_clemsa_test) { "Test decoder " SUBGHZ_PROTOCOL_CLEMSA_NAME " error\r\n"); } +MU_TEST(subghz_decoder_oregon2_test) { + mu_assert( + subghz_decoder_test( + EXT_PATH("unit_tests/subghz/oregon2_raw.sub"), SUBGHZ_PROTOCOL_OREGON2_NAME), + "Test decoder " SUBGHZ_PROTOCOL_OREGON2_NAME " error\r\n"); +} + //test encoders MU_TEST(subghz_encoder_princeton_test) { mu_assert( @@ -595,6 +602,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_decoder_magellen_test); MU_RUN_TEST(subghz_decoder_intertechno_v3_test); MU_RUN_TEST(subghz_decoder_clemsa_test); + MU_RUN_TEST(subghz_decoder_oregon2_test); MU_RUN_TEST(subghz_encoder_princeton_test); MU_RUN_TEST(subghz_encoder_came_test); diff --git a/applications/unit_tests/test_index.c b/applications/debug/unit_tests/test_index.c similarity index 100% rename from applications/unit_tests/test_index.c rename to applications/debug/unit_tests/test_index.c diff --git a/applications/unit_tests/varint/varint_test.c b/applications/debug/unit_tests/varint/varint_test.c similarity index 100% rename from applications/unit_tests/varint/varint_test.c rename to applications/debug/unit_tests/varint/varint_test.c diff --git a/applications/debug/usb_mouse/application.fam b/applications/debug/usb_mouse/application.fam new file mode 100644 index 00000000..5c434004 --- /dev/null +++ b/applications/debug/usb_mouse/application.fam @@ -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", +) diff --git a/applications/debug_tools/usb_mouse.c b/applications/debug/usb_mouse/usb_mouse.c similarity index 100% rename from applications/debug_tools/usb_mouse.c rename to applications/debug/usb_mouse/usb_mouse.c diff --git a/applications/debug/usb_test/application.fam b/applications/debug/usb_test/application.fam new file mode 100644 index 00000000..27395c34 --- /dev/null +++ b/applications/debug/usb_test/application.fam @@ -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", +) diff --git a/applications/debug_tools/usb_test.c b/applications/debug/usb_test/usb_test.c similarity index 100% rename from applications/debug_tools/usb_test.c rename to applications/debug/usb_test/usb_test.c diff --git a/applications/debug/vibro_test/application.fam b/applications/debug/vibro_test/application.fam new file mode 100644 index 00000000..f7115cc9 --- /dev/null +++ b/applications/debug/vibro_test/application.fam @@ -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", +) diff --git a/applications/debug_tools/vibro_test.c b/applications/debug/vibro_test/vibro_test.c similarity index 100% rename from applications/debug_tools/vibro_test.c rename to applications/debug/vibro_test/vibro_test.c diff --git a/applications/debug_tools/application.fam b/applications/debug_tools/application.fam deleted file mode 100644 index 8cb495b0..00000000 --- a/applications/debug_tools/application.fam +++ /dev/null @@ -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, -) diff --git a/applications/desktop/views/desktop_view_lock_menu.c b/applications/desktop/views/desktop_view_lock_menu.c deleted file mode 100644 index 97d3c489..00000000 --- a/applications/desktop/views/desktop_view_lock_menu.c +++ /dev/null @@ -1,130 +0,0 @@ -#include -#include - -#include "../desktop_i.h" -#include "desktop_view_lock_menu.h" - -#define LOCK_MENU_ITEMS_NB 3 - -void desktop_lock_menu_set_callback( - DesktopLockMenuView* lock_menu, - DesktopLockMenuViewCallback callback, - void* context) { - furi_assert(lock_menu); - furi_assert(callback); - lock_menu->callback = callback; - lock_menu->context = context; -} - -void desktop_lock_menu_pin_set(DesktopLockMenuView* lock_menu, bool pin_is_set) { - with_view_model( - lock_menu->view, (DesktopLockMenuViewModel * model) { - model->pin_set = pin_is_set; - return true; - }); -} - -void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx) { - furi_assert(idx < LOCK_MENU_ITEMS_NB); - with_view_model( - lock_menu->view, (DesktopLockMenuViewModel * model) { - model->idx = idx; - return true; - }); -} - -static void lock_menu_callback(void* context, uint8_t index) { - furi_assert(context); - DesktopLockMenuView* lock_menu = context; - switch(index) { - case 0: // lock - lock_menu->callback(DesktopLockMenuEventLock, lock_menu->context); - break; - case 1: // lock - lock_menu->callback(DesktopLockMenuEventPinLock, lock_menu->context); - break; - default: // wip message - with_view_model( - lock_menu->view, (DesktopLockMenuViewModel * model) { - model->hint_timeout = HINT_TIMEOUT; - return true; - }); - break; - } -} - -void desktop_lock_menu_render(Canvas* canvas, void* model) { - const char* Lockmenu_Items[LOCK_MENU_ITEMS_NB] = {"Lock", "Lock with PIN", "DUMB mode"}; - - DesktopLockMenuViewModel* m = model; - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_draw_icon(canvas, -57, 0 + STATUS_BAR_Y_SHIFT, &I_DoorLeft_70x55); - canvas_draw_icon(canvas, 116, 0 + STATUS_BAR_Y_SHIFT, &I_DoorRight_70x55); - canvas_set_font(canvas, FontSecondary); - - for(uint8_t i = 0; i < LOCK_MENU_ITEMS_NB; ++i) { - const char* str = Lockmenu_Items[i]; - - if(i == 1 && !m->pin_set) str = "Set PIN"; - if(m->hint_timeout && m->idx == 2 && m->idx == i) str = "Not Implemented"; - - if(str != NULL) - canvas_draw_str_aligned( - canvas, 64, 9 + (i * 17) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str); - - if(m->idx == i) elements_frame(canvas, 15, 1 + (i * 17) + STATUS_BAR_Y_SHIFT, 98, 15); - } -} - -View* desktop_lock_menu_get_view(DesktopLockMenuView* lock_menu) { - furi_assert(lock_menu); - return lock_menu->view; -} - -bool desktop_lock_menu_input(InputEvent* event, void* context) { - furi_assert(event); - furi_assert(context); - - DesktopLockMenuView* lock_menu = context; - uint8_t idx; - - if(event->type != InputTypeShort) return false; - with_view_model( - lock_menu->view, (DesktopLockMenuViewModel * model) { - model->hint_timeout = 0; // clear hint timeout - if(event->key == InputKeyUp) { - model->idx = CLAMP(model->idx - 1, LOCK_MENU_ITEMS_NB - 1, 0); - } else if(event->key == InputKeyDown) { - model->idx = CLAMP(model->idx + 1, LOCK_MENU_ITEMS_NB - 1, 0); - } - idx = model->idx; - return true; - }); - - if(event->key == InputKeyBack) { - lock_menu->callback(DesktopLockMenuEventExit, lock_menu->context); - } else if(event->key == InputKeyOk) { - lock_menu_callback(lock_menu, idx); - } - - return true; -} - -DesktopLockMenuView* desktop_lock_menu_alloc() { - DesktopLockMenuView* lock_menu = malloc(sizeof(DesktopLockMenuView)); - lock_menu->view = view_alloc(); - view_allocate_model(lock_menu->view, ViewModelTypeLocking, sizeof(DesktopLockMenuViewModel)); - view_set_context(lock_menu->view, lock_menu); - view_set_draw_callback(lock_menu->view, (ViewDrawCallback)desktop_lock_menu_render); - view_set_input_callback(lock_menu->view, desktop_lock_menu_input); - - return lock_menu; -} - -void desktop_lock_menu_free(DesktopLockMenuView* lock_menu_view) { - furi_assert(lock_menu_view); - - view_free(lock_menu_view->view); - free(lock_menu_view); -} diff --git a/applications/extapps.scons b/applications/extapps.scons deleted file mode 100644 index 11b59757..00000000 --- a/applications/extapps.scons +++ /dev/null @@ -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") diff --git a/applications/gui/application.fam b/applications/gui/application.fam deleted file mode 100644 index 0116f5b8..00000000 --- a/applications/gui/application.fam +++ /dev/null @@ -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, -) diff --git a/applications/gui/modules/dialog.c b/applications/gui/modules/dialog.c deleted file mode 100644 index 5d36f93f..00000000 --- a/applications/gui/modules/dialog.c +++ /dev/null @@ -1,131 +0,0 @@ -#include "dialog.h" -#include -#include - -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; - }); -} diff --git a/applications/gui/modules/dialog.h b/applications/gui/modules/dialog.h deleted file mode 100644 index e9160a35..00000000 --- a/applications/gui/modules/dialog.h +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @file dialog.h - * GUI: Dialog view module API - */ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** Dialog anonymous structure */ -typedef struct Dialog Dialog; - -/** Dialog result */ -typedef enum { - DialogResultLeft, - DialogResultRight, - DialogResultBack, -} DialogResult; - -/** Dialog result callback type - * @warning comes from GUI thread - */ -typedef void (*DialogResultCallback)(DialogResult result, void* context); - -/** Allocate and initialize dialog - * - * This dialog used to ask simple questions like Yes/ - * - * @return Dialog instance - */ -Dialog* dialog_alloc(); - -/** Deinitialize and free dialog - * - * @param dialog Dialog instance - */ -void dialog_free(Dialog* dialog); - -/** Get dialog view - * - * @param dialog Dialog instance - * - * @return View instance that can be used for embedding - */ -View* dialog_get_view(Dialog* dialog); - -/** Set dialog result callback - * - * @param dialog Dialog instance - * @param callback result callback function - */ -void dialog_set_result_callback(Dialog* dialog, DialogResultCallback callback); - -/** Set dialog context - * - * @param dialog Dialog instance - * @param context context pointer, will be passed to result callback - */ -void dialog_set_context(Dialog* dialog, void* context); - -/** Set dialog header text - * - * @param dialog Dialog instance - * @param text text to be shown - */ -void dialog_set_header_text(Dialog* dialog, const char* text); - -/** Set dialog text - * - * @param dialog Dialog instance - * @param text text to be shown - */ -void dialog_set_text(Dialog* dialog, const char* text); - -/** Set left button text - * - * @param dialog Dialog instance - * @param text text to be shown - */ -void dialog_set_left_button_text(Dialog* dialog, const char* text); - -/** Set right button text - * - * @param dialog Dialog instance - * @param text text to be shown - */ -void dialog_set_right_button_text(Dialog* dialog, const char* text); - -#ifdef __cplusplus -} -#endif diff --git a/applications/lfrfid/lfrfid_app.cpp b/applications/lfrfid/lfrfid_app.cpp deleted file mode 100644 index 9373ca8c..00000000 --- a/applications/lfrfid/lfrfid_app.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include "lfrfid_app.h" -#include "assets_icons.h" -#include -#include "m-string.h" -#include "scene/lfrfid_app_scene_start.h" -#include "scene/lfrfid_app_scene_read.h" -#include "scene/lfrfid_app_scene_read_success.h" -#include "scene/lfrfid_app_scene_retry_confirm.h" -#include "scene/lfrfid_app_scene_exit_confirm.h" -#include "scene/lfrfid_app_scene_read_menu.h" -#include "scene/lfrfid_app_scene_write.h" -#include "scene/lfrfid_app_scene_write_success.h" -#include "scene/lfrfid_app_scene_emulate.h" -#include "scene/lfrfid_app_scene_save_name.h" -#include "scene/lfrfid_app_scene_save_success.h" -#include "scene/lfrfid_app_scene_select_key.h" -#include "scene/lfrfid_app_scene_saved_key_menu.h" -#include "scene/lfrfid_app_scene_save_data.h" -#include "scene/lfrfid_app_scene_save_type.h" -#include "scene/lfrfid_app_scene_saved_info.h" -#include "scene/lfrfid_app_scene_delete_confirm.h" -#include "scene/lfrfid_app_scene_delete_success.h" -#include "scene/lfrfid_app_scene_rpc.h" -#include "scene/lfrfid_app_scene_extra_actions.h" -#include "scene/lfrfid_app_scene_raw_info.h" -#include "scene/lfrfid_app_scene_raw_name.h" -#include "scene/lfrfid_app_scene_raw_read.h" -#include "scene/lfrfid_app_scene_raw_success.h" - -#include -#include - -#include - -const char* LfRfidApp::app_folder = ANY_PATH("lfrfid"); -const char* LfRfidApp::app_sd_folder = EXT_PATH("lfrfid"); -const char* LfRfidApp::app_extension = ".rfid"; -const char* LfRfidApp::app_filetype = "Flipper RFID key"; - -LfRfidApp::LfRfidApp() - : scene_controller{this} - , notification{RECORD_NOTIFICATION} - , storage{RECORD_STORAGE} - , dialogs{RECORD_DIALOGS} - , text_store(40) { - string_init(file_name); - string_init(raw_file_name); - string_init_set_str(file_path, app_folder); - - dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax); - - size_t size = protocol_dict_get_max_data_size(dict); - new_key_data = (uint8_t*)malloc(size); - old_key_data = (uint8_t*)malloc(size); - - lfworker = lfrfid_worker_alloc(dict); -} - -LfRfidApp::~LfRfidApp() { - string_clear(raw_file_name); - string_clear(file_name); - string_clear(file_path); - protocol_dict_free(dict); - - lfrfid_worker_free(lfworker); - - if(rpc_ctx) { - rpc_system_app_set_callback(rpc_ctx, NULL, NULL); - rpc_system_app_send_exited(rpc_ctx); - } - - free(new_key_data); - free(old_key_data); -} - -static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) { - furi_assert(context); - LfRfidApp* app = static_cast(context); - - if(rpc_event == RpcAppEventSessionClose) { - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::RpcSessionClose; - app->view_controller.send_event(&event); - // Detach RPC - rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL); - app->rpc_ctx = NULL; - } else if(rpc_event == RpcAppEventAppExit) { - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Exit; - app->view_controller.send_event(&event); - } else if(rpc_event == RpcAppEventLoadFile) { - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::RpcLoadFile; - app->view_controller.send_event(&event); - } else { - rpc_system_app_confirm(app->rpc_ctx, rpc_event, false); - } -} - -void LfRfidApp::run(void* _args) { - const char* args = reinterpret_cast(_args); - - make_app_folder(); - - if(args && strlen(args)) { - uint32_t rpc_ctx_ptr = 0; - if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) { - rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr; - rpc_system_app_set_callback(rpc_ctx, rpc_command_callback, this); - rpc_system_app_send_started(rpc_ctx); - view_controller.attach_to_gui(ViewDispatcherTypeDesktop); - scene_controller.add_scene(SceneType::Rpc, new LfRfidAppSceneRpc()); - scene_controller.process(100, SceneType::Rpc); - } else { - string_set_str(file_path, args); - load_key_data(file_path, true); - view_controller.attach_to_gui(ViewDispatcherTypeFullscreen); - scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate()); - scene_controller.process(100, SceneType::Emulate); - } - - } else { - view_controller.attach_to_gui(ViewDispatcherTypeFullscreen); - scene_controller.add_scene(SceneType::Start, new LfRfidAppSceneStart()); - scene_controller.add_scene(SceneType::Read, new LfRfidAppSceneRead()); - scene_controller.add_scene(SceneType::RetryConfirm, new LfRfidAppSceneRetryConfirm()); - scene_controller.add_scene(SceneType::ExitConfirm, new LfRfidAppSceneExitConfirm()); - scene_controller.add_scene(SceneType::ReadSuccess, new LfRfidAppSceneReadSuccess()); - scene_controller.add_scene(SceneType::ReadKeyMenu, new LfRfidAppSceneReadKeyMenu()); - scene_controller.add_scene(SceneType::Write, new LfRfidAppSceneWrite()); - scene_controller.add_scene(SceneType::WriteSuccess, new LfRfidAppSceneWriteSuccess()); - scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate()); - scene_controller.add_scene(SceneType::SaveName, new LfRfidAppSceneSaveName()); - scene_controller.add_scene(SceneType::SaveSuccess, new LfRfidAppSceneSaveSuccess()); - scene_controller.add_scene(SceneType::SelectKey, new LfRfidAppSceneSelectKey()); - scene_controller.add_scene(SceneType::SavedKeyMenu, new LfRfidAppSceneSavedKeyMenu()); - scene_controller.add_scene(SceneType::SaveData, new LfRfidAppSceneSaveData()); - scene_controller.add_scene(SceneType::SaveType, new LfRfidAppSceneSaveType()); - scene_controller.add_scene(SceneType::SavedInfo, new LfRfidAppSceneSavedInfo()); - scene_controller.add_scene(SceneType::DeleteConfirm, new LfRfidAppSceneDeleteConfirm()); - scene_controller.add_scene(SceneType::DeleteSuccess, new LfRfidAppSceneDeleteSuccess()); - scene_controller.add_scene(SceneType::ExtraActions, new LfRfidAppSceneExtraActions()); - scene_controller.add_scene(SceneType::RawInfo, new LfRfidAppSceneRawInfo()); - scene_controller.add_scene(SceneType::RawName, new LfRfidAppSceneRawName()); - scene_controller.add_scene(SceneType::RawRead, new LfRfidAppSceneRawRead()); - scene_controller.add_scene(SceneType::RawSuccess, new LfRfidAppSceneRawSuccess()); - scene_controller.process(100); - } -} - -bool LfRfidApp::save_key() { - bool result = false; - - make_app_folder(); - - if(string_end_with_str_p(file_path, app_extension)) { - size_t filename_start = string_search_rchar(file_path, '/'); - string_left(file_path, filename_start); - } - - string_cat_printf(file_path, "/%s%s", string_get_cstr(file_name), app_extension); - - result = save_key_data(file_path); - return result; -} - -bool LfRfidApp::load_key_from_file_select(bool need_restore) { - if(!need_restore) { - string_set_str(file_path, app_folder); - } - - bool result = dialog_file_browser_show( - dialogs, file_path, file_path, app_extension, true, &I_125_10px, true); - - if(result) { - result = load_key_data(file_path, true); - } - - return result; -} - -bool LfRfidApp::delete_key() { - return storage_simply_remove(storage, string_get_cstr(file_path)); -} - -bool LfRfidApp::load_key_data(string_t path, bool show_dialog) { - bool result = false; - - do { - protocol_id = lfrfid_dict_file_load(dict, string_get_cstr(path)); - if(protocol_id == PROTOCOL_NO) break; - - path_extract_filename(path, file_name, true); - result = true; - } while(0); - - if((!result) && (show_dialog)) { - dialog_message_show_storage_error(dialogs, "Cannot load\nkey file"); - } - - return result; -} - -bool LfRfidApp::save_key_data(string_t path) { - bool result = lfrfid_dict_file_save(dict, protocol_id, string_get_cstr(path)); - - if(!result) { - dialog_message_show_storage_error(dialogs, "Cannot save\nkey file"); - } - - return result; -} - -void LfRfidApp::make_app_folder() { - if(!storage_simply_mkdir(storage, app_folder)) { - dialog_message_show_storage_error(dialogs, "Cannot create\napp folder"); - } -} diff --git a/applications/lfrfid/lfrfid_app.h b/applications/lfrfid/lfrfid_app.h deleted file mode 100644 index 153218db..00000000 --- a/applications/lfrfid/lfrfid_app.h +++ /dev/null @@ -1,137 +0,0 @@ -#pragma once -#include "m-string.h" -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include "view/container_vm.h" - -#include -#include -#include - -#include "rpc/rpc_app.h" - -#include -#include -#include -#include - -#define LFRFID_KEY_NAME_SIZE 22 - -class LfRfidApp { -public: - enum class EventType : uint8_t { - GENERIC_EVENT_ENUM_VALUES, - Next, - MenuSelected, - Stay, - Retry, - Exit, - ReadEventSenseStart, - ReadEventSenseEnd, - ReadEventSenseCardStart, - ReadEventSenseCardEnd, - ReadEventStartASK, - ReadEventStartPSK, - ReadEventDone, - ReadEventOverrun, - ReadEventError, - WriteEventOK, - WriteEventProtocolCannotBeWritten, - WriteEventFobCannotBeWritten, - WriteEventTooLongToWrite, - RpcLoadFile, - RpcSessionClose, - }; - - enum class SceneType : uint8_t { - GENERIC_SCENE_ENUM_VALUES, - Read, - ReadSuccess, - RetryConfirm, - ExitConfirm, - ReadKeyMenu, - Write, - WriteSuccess, - Emulate, - SaveName, - SaveSuccess, - SelectKey, - SavedKeyMenu, - SaveData, - SaveType, - SavedInfo, - DeleteConfirm, - DeleteSuccess, - Rpc, - ExtraActions, - RawInfo, - RawName, - RawRead, - RawSuccess, - }; - - class Event { - public: - union { - int32_t signed_int; - } payload; - - EventType type; - }; - - SceneController, LfRfidApp> scene_controller; - ViewController - view_controller; - - ~LfRfidApp(); - LfRfidApp(); - - RecordController notification; - RecordController storage; - RecordController dialogs; - - TextStore text_store; - - string_t file_path; - - RpcAppSystem* rpc_ctx; - - void run(void* args); - - static const char* app_folder; - static const char* app_sd_folder; - static const char* app_extension; - static const char* app_filetype; - - bool save_key(); - bool load_key_from_file_select(bool need_restore); - bool delete_key(); - - bool load_key_data(string_t path, bool show_dialog); - bool save_key_data(string_t path); - - void make_app_folder(); - - ProtocolDict* dict; - LFRFIDWorker* lfworker; - string_t file_name; - ProtocolId protocol_id; - LFRFIDWorkerReadType read_type; - - uint8_t* old_key_data; - uint8_t* new_key_data; - - string_t raw_file_name; -}; diff --git a/applications/lfrfid/lfrfid_app_launcher.cpp b/applications/lfrfid/lfrfid_app_launcher.cpp deleted file mode 100644 index 2855850f..00000000 --- a/applications/lfrfid/lfrfid_app_launcher.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "lfrfid_app.h" - -// app enter function -extern "C" int32_t lfrfid_app(void* args) { - LfRfidApp* app = new LfRfidApp(); - app->run(args); - delete app; - - return 0; -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.cpp b/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.cpp deleted file mode 100644 index 58ff4dcd..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "lfrfid_app_scene_delete_confirm.h" -#include "../view/elements/button_element.h" -#include "../view/elements/icon_element.h" -#include "../view/elements/string_element.h" - -void LfRfidAppSceneDeleteConfirm::on_enter(LfRfidApp* app, bool /* need_restore */) { - string_init(string_data); - string_init(string_header); - - auto container = app->view_controller.get(); - - auto button = container->add(); - button->set_type(ButtonElement::Type::Left, "Back"); - button->set_callback(app, LfRfidAppSceneDeleteConfirm::back_callback); - - button = container->add(); - button->set_type(ButtonElement::Type::Right, "Delete"); - button->set_callback(app, LfRfidAppSceneDeleteConfirm::delete_callback); - - auto line_1 = container->add(); - auto line_2 = container->add(); - auto line_3 = container->add(); - - size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); - uint8_t* data = (uint8_t*)malloc(size); - protocol_dict_get_data(app->dict, app->protocol_id, data, size); - for(uint8_t i = 0; i < MIN(size, (size_t)8); i++) { - if(i != 0) { - string_cat_printf(string_data, " "); - } - - string_cat_printf(string_data, "%02X", data[i]); - } - free(data); - - string_printf(string_header, "Delete %s?", string_get_cstr(app->file_name)); - line_1->set_text( - string_get_cstr(string_header), 64, 0, 128 - 2, AlignCenter, AlignTop, FontPrimary); - line_2->set_text( - string_get_cstr(string_data), 64, 19, 0, AlignCenter, AlignTop, FontSecondary); - line_3->set_text( - protocol_dict_get_name(app->dict, app->protocol_id), - 64, - 49, - 0, - AlignCenter, - AlignBottom, - FontSecondary); - - app->view_controller.switch_to(); -} - -bool LfRfidAppSceneDeleteConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::Next) { - app->delete_key(); - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::DeleteSuccess); - consumed = true; - } else if(event->type == LfRfidApp::EventType::Stay) { - app->scene_controller.switch_to_previous_scene(); - consumed = true; - } else if(event->type == LfRfidApp::EventType::Back) { - consumed = true; - } - - return consumed; -} - -void LfRfidAppSceneDeleteConfirm::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); - string_clear(string_data); - string_clear(string_header); -} - -void LfRfidAppSceneDeleteConfirm::back_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Stay; - app->view_controller.send_event(&event); -} - -void LfRfidAppSceneDeleteConfirm::delete_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Next; - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.h b/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.h deleted file mode 100644 index f9daed54..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneDeleteConfirm : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void back_callback(void* context); - static void delete_callback(void* context); - - string_t string_header; - string_t string_data; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_delete_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_delete_success.cpp deleted file mode 100644 index 9820338d..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_delete_success.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "lfrfid_app_scene_delete_success.h" - -void LfRfidAppSceneDeleteSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) { - auto popup = app->view_controller.get(); - - popup->set_icon(0, 2, &I_DolphinMafia_115x62); - popup->set_header("Deleted", 83, 19, AlignLeft, AlignBottom); - popup->set_context(app); - popup->set_callback(LfRfidAppSceneDeleteSuccess::timeout_callback); - popup->set_timeout(1500); - popup->enable_timeout(); - - app->view_controller.switch_to(); -} - -bool LfRfidAppSceneDeleteSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::Back) { - app->scene_controller.search_and_switch_to_previous_scene( - {LfRfidApp::SceneType::SelectKey}); - - consumed = true; - } - - return consumed; -} - -void LfRfidAppSceneDeleteSuccess::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); -} - -void LfRfidAppSceneDeleteSuccess::timeout_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Back; - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_delete_success.h b/applications/lfrfid/scene/lfrfid_app_scene_delete_success.h deleted file mode 100644 index 009b9f25..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_delete_success.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneDeleteSuccess : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void timeout_callback(void* context); -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_emulate.cpp b/applications/lfrfid/scene/lfrfid_app_scene_emulate.cpp deleted file mode 100644 index 02cb011d..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_emulate.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "lfrfid_app_scene_emulate.h" -#include -#include - -void LfRfidAppSceneEmulate::on_enter(LfRfidApp* app, bool /* need_restore */) { - DOLPHIN_DEED(DolphinDeedRfidEmulate); - auto popup = app->view_controller.get(); - - popup->set_header("Emulating", 89, 30, AlignCenter, AlignTop); - if(string_size(app->file_name)) { - popup->set_text(string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop); - } else { - popup->set_text( - protocol_dict_get_name(app->dict, app->protocol_id), 89, 43, AlignCenter, AlignTop); - } - popup->set_icon(0, 3, &I_RFIDDolphinSend_97x61); - - app->view_controller.switch_to(); - lfrfid_worker_start_thread(app->lfworker); - lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id); - notification_message(app->notification, &sequence_blink_start_magenta); -} - -bool LfRfidAppSceneEmulate::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - UNUSED(app); - UNUSED(event); - bool consumed = false; - return consumed; -} - -void LfRfidAppSceneEmulate::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); - lfrfid_worker_stop(app->lfworker); - lfrfid_worker_stop_thread(app->lfworker); - notification_message(app->notification, &sequence_blink_stop); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_emulate.h b/applications/lfrfid/scene/lfrfid_app_scene_emulate.h deleted file mode 100644 index 13d2b857..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_emulate.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneEmulate : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp b/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp deleted file mode 100644 index be070b40..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "lfrfid_app_scene_exit_confirm.h" -#include "../view/elements/button_element.h" -#include "../view/elements/icon_element.h" -#include "../view/elements/string_element.h" - -void LfRfidAppSceneExitConfirm::on_enter(LfRfidApp* app, bool /* need_restore */) { - auto container = app->view_controller.get(); - - auto button = container->add(); - button->set_type(ButtonElement::Type::Left, "Exit"); - button->set_callback(app, LfRfidAppSceneExitConfirm::exit_callback); - - button = container->add(); - button->set_type(ButtonElement::Type::Right, "Stay"); - button->set_callback(app, LfRfidAppSceneExitConfirm::stay_callback); - - auto line_1 = container->add(); - auto line_2 = container->add(); - - line_1->set_text("Exit to RFID Menu?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary); - line_2->set_text( - "All unsaved data will be lost!", 64, 31, 0, AlignCenter, AlignBottom, FontSecondary); - - app->view_controller.switch_to(); -} - -bool LfRfidAppSceneExitConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::Next) { - app->scene_controller.search_and_switch_to_previous_scene({LfRfidApp::SceneType::Start}); - consumed = true; - } else if(event->type == LfRfidApp::EventType::Stay) { - app->scene_controller.switch_to_previous_scene(); - consumed = true; - } else if(event->type == LfRfidApp::EventType::Back) { - consumed = true; - } - - return consumed; -} - -void LfRfidAppSceneExitConfirm::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); -} - -void LfRfidAppSceneExitConfirm::exit_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Next; - app->view_controller.send_event(&event); -} - -void LfRfidAppSceneExitConfirm::stay_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Stay; - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.h b/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.h deleted file mode 100644 index a0a10232..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneExitConfirm : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void exit_callback(void* context); - static void stay_callback(void* context); -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_extra_actions.cpp b/applications/lfrfid/scene/lfrfid_app_scene_extra_actions.cpp deleted file mode 100644 index ea4f03db..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_extra_actions.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "lfrfid_app_scene_extra_actions.h" - -typedef enum { - SubmenuASK, - SubmenuPSK, - SubmenuRAW, -} SubmenuIndex; - -void LfRfidAppSceneExtraActions::on_enter(LfRfidApp* app, bool need_restore) { - auto submenu = app->view_controller.get(); - - submenu->add_item("Read ASK (Animal, Ordinary Card)", SubmenuASK, submenu_callback, app); - submenu->add_item("Read PSK (Indala)", SubmenuPSK, submenu_callback, app); - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - submenu->add_item("Read RAW RFID data", SubmenuRAW, submenu_callback, app); - } - - if(need_restore) { - submenu->set_selected_item(submenu_item_selected); - } - - app->view_controller.switch_to(); -} - -bool LfRfidAppSceneExtraActions::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::MenuSelected) { - submenu_item_selected = event->payload.signed_int; - switch(event->payload.signed_int) { - case SubmenuASK: - app->read_type = LFRFIDWorkerReadTypeASKOnly; - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Read); - break; - case SubmenuPSK: - app->read_type = LFRFIDWorkerReadTypePSKOnly; - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Read); - break; - case SubmenuRAW: - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::RawName); - break; - } - - consumed = true; - } - - return consumed; -} - -void LfRfidAppSceneExtraActions::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); -} - -void LfRfidAppSceneExtraActions::submenu_callback(void* context, uint32_t index) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - - event.type = LfRfidApp::EventType::MenuSelected; - event.payload.signed_int = index; - - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_extra_actions.h b/applications/lfrfid/scene/lfrfid_app_scene_extra_actions.h deleted file mode 100644 index dcd74614..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_extra_actions.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneExtraActions : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void submenu_callback(void* context, uint32_t index); - uint32_t submenu_item_selected = 0; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_info.cpp b/applications/lfrfid/scene/lfrfid_app_scene_raw_info.cpp deleted file mode 100644 index ce3634b2..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_raw_info.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "lfrfid_app_scene_raw_info.h" -#include "../view/elements/button_element.h" -#include "../view/elements/icon_element.h" -#include "../view/elements/string_element.h" - -static void ok_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Next; - app->view_controller.send_event(&event); -} - -static void back_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Back; - app->view_controller.send_event(&event); -} - -void LfRfidAppSceneRawInfo::on_enter(LfRfidApp* app, bool /* need_restore */) { - string_init(string_info); - - auto container = app->view_controller.get(); - - bool sd_exist = storage_sd_status(app->storage) == FSE_OK; - if(!sd_exist) { - auto icon = container->add(); - icon->set_icon(0, 0, &I_SDQuestion_35x43); - auto line = container->add(); - line->set_text( - "No SD card found.\nThis function will not\nwork without\nSD card.", - 81, - 4, - 0, - AlignCenter, - AlignTop, - FontSecondary); - - auto button = container->add(); - button->set_type(ButtonElement::Type::Left, "Back"); - button->set_callback(app, back_callback); - } else { - string_printf( - string_info, - "RAW RFID data reader\r\n" - "1) Put the Flipper on your card\r\n" - "2) Press OK\r\n" - "3) Wait until data is read"); - - auto line = container->add(); - line->set_text(string_get_cstr(string_info), 0, 1, 0, AlignLeft, AlignTop, FontSecondary); - - auto button = container->add(); - button->set_type(ButtonElement::Type::Center, "OK"); - button->set_callback(app, ok_callback); - } - - app->view_controller.switch_to(); -} - -bool LfRfidAppSceneRawInfo::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - if(event->type == LfRfidApp::EventType::Next) { - app->scene_controller.switch_to_scene({LfRfidApp::SceneType::RawRead}); - consumed = true; - } else if(event->type == LfRfidApp::EventType::Back) { - app->scene_controller.search_and_switch_to_previous_scene( - {LfRfidApp::SceneType::ExtraActions}); - consumed = true; - } - return consumed; -} - -void LfRfidAppSceneRawInfo::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); - string_clear(string_info); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_info.h b/applications/lfrfid/scene/lfrfid_app_scene_raw_info.h deleted file mode 100644 index eecca143..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_raw_info.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneRawInfo : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - string_t string_info; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_name.cpp b/applications/lfrfid/scene/lfrfid_app_scene_raw_name.cpp deleted file mode 100644 index 0ad34619..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_raw_name.cpp +++ /dev/null @@ -1,46 +0,0 @@ - -#include "lfrfid_app_scene_raw_name.h" -#include "m-string.h" -#include -#include - -void LfRfidAppSceneRawName::on_enter(LfRfidApp* app, bool /* need_restore */) { - const char* key_name = string_get_cstr(app->raw_file_name); - - bool key_name_empty = (string_size(app->raw_file_name) == 0); - if(key_name_empty) { - app->text_store.set("RfidRecord"); - } else { - app->text_store.set("%s", key_name); - } - - auto text_input = app->view_controller.get(); - text_input->set_header_text("Name the raw file"); - - text_input->set_result_callback( - save_callback, app, app->text_store.text, LFRFID_KEY_NAME_SIZE, key_name_empty); - - app->view_controller.switch_to(); -} - -bool LfRfidAppSceneRawName::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::Next) { - string_set_str(app->raw_file_name, app->text_store.text); - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::RawInfo); - } - - return consumed; -} - -void LfRfidAppSceneRawName::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); -} - -void LfRfidAppSceneRawName::save_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Next; - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_name.h b/applications/lfrfid/scene/lfrfid_app_scene_raw_name.h deleted file mode 100644 index 225d135e..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_raw_name.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneRawName : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void save_callback(void* context); -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_read.cpp b/applications/lfrfid/scene/lfrfid_app_scene_raw_read.cpp deleted file mode 100644 index 0d04e6bc..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_raw_read.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include "lfrfid_app_scene_raw_read.h" -#include - -#define RAW_READ_TIME 5000 - -static void lfrfid_read_callback(LFRFIDWorkerReadRawResult result, void* ctx) { - LfRfidApp* app = static_cast(ctx); - LfRfidApp::Event event; - - switch(result) { - case LFRFIDWorkerReadRawFileError: - event.type = LfRfidApp::EventType::ReadEventError; - break; - case LFRFIDWorkerReadRawOverrun: - event.type = LfRfidApp::EventType::ReadEventOverrun; - break; - } - - app->view_controller.send_event(&event); -} - -static void timer_callback(void* ctx) { - LfRfidApp* app = static_cast(ctx); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::ReadEventDone; - app->view_controller.send_event(&event); -} - -void LfRfidAppSceneRawRead::on_enter(LfRfidApp* app, bool /* need_restore */) { - string_init(string_file_name); - auto popup = app->view_controller.get(); - popup->set_icon(0, 3, &I_RFIDDolphinReceive_97x61); - app->view_controller.switch_to(); - lfrfid_worker_start_thread(app->lfworker); - app->make_app_folder(); - - timer = furi_timer_alloc(timer_callback, FuriTimerTypeOnce, app); - furi_timer_start(timer, RAW_READ_TIME); - string_printf( - string_file_name, "%s/%s.ask.raw", app->app_sd_folder, string_get_cstr(app->raw_file_name)); - popup->set_header("Reading\nRAW RFID\nASK", 89, 30, AlignCenter, AlignTop); - lfrfid_worker_read_raw_start( - app->lfworker, - string_get_cstr(string_file_name), - LFRFIDWorkerReadTypeASKOnly, - lfrfid_read_callback, - app); - - notification_message(app->notification, &sequence_blink_start_cyan); - - is_psk = false; - error = false; -} - -bool LfRfidAppSceneRawRead::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - UNUSED(app); - bool consumed = true; - auto popup = app->view_controller.get(); - - switch(event->type) { - case LfRfidApp::EventType::ReadEventError: - error = true; - popup->set_header("Reading\nRAW RFID\nFile error", 89, 30, AlignCenter, AlignTop); - notification_message(app->notification, &sequence_blink_start_red); - furi_timer_stop(timer); - break; - case LfRfidApp::EventType::ReadEventDone: - if(!error) { - if(is_psk) { - notification_message(app->notification, &sequence_success); - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::RawSuccess); - } else { - popup->set_header("Reading\nRAW RFID\nPSK", 89, 30, AlignCenter, AlignTop); - notification_message(app->notification, &sequence_blink_start_yellow); - lfrfid_worker_stop(app->lfworker); - string_printf( - string_file_name, - "%s/%s.psk.raw", - app->app_sd_folder, - string_get_cstr(app->raw_file_name)); - lfrfid_worker_read_raw_start( - app->lfworker, - string_get_cstr(string_file_name), - LFRFIDWorkerReadTypePSKOnly, - lfrfid_read_callback, - app); - furi_timer_start(timer, RAW_READ_TIME); - is_psk = true; - } - } - break; - default: - consumed = false; - break; - } - - return consumed; -} - -void LfRfidAppSceneRawRead::on_exit(LfRfidApp* app) { - notification_message(app->notification, &sequence_blink_stop); - app->view_controller.get()->clean(); - lfrfid_worker_stop(app->lfworker); - lfrfid_worker_stop_thread(app->lfworker); - furi_timer_free(timer); - string_clear(string_file_name); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_read.h b/applications/lfrfid/scene/lfrfid_app_scene_raw_read.h deleted file mode 100644 index 09ef7463..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_raw_read.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneRawRead : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - string_t string_file_name; - FuriTimer* timer; - bool is_psk; - bool error; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_raw_success.cpp deleted file mode 100644 index 227ab580..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_raw_success.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "lfrfid_app_scene_raw_success.h" -#include "../view/elements/button_element.h" -#include "../view/elements/icon_element.h" -#include "../view/elements/string_element.h" - -void LfRfidAppSceneRawSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) { - string_init(string_info); - - string_printf(string_info, "RAW RFID read success!\r\n"); - string_cat_printf(string_info, "Now you can analyze files\r\n"); - string_cat_printf(string_info, "Or send them to developers"); - - auto container = app->view_controller.get(); - - auto line = container->add(); - line->set_text(string_get_cstr(string_info), 0, 1, 0, AlignLeft, AlignTop, FontSecondary); - - auto button = container->add(); - button->set_type(ButtonElement::Type::Center, "OK"); - button->set_callback(app, LfRfidAppSceneRawSuccess::ok_callback); - - app->view_controller.switch_to(); -} - -bool LfRfidAppSceneRawSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - if(event->type == LfRfidApp::EventType::Next) { - app->scene_controller.search_and_switch_to_previous_scene( - {LfRfidApp::SceneType::ExtraActions}); - consumed = true; - } - return consumed; -} - -void LfRfidAppSceneRawSuccess::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); - string_clear(string_info); -} - -void LfRfidAppSceneRawSuccess::ok_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Next; - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_success.h b/applications/lfrfid/scene/lfrfid_app_scene_raw_success.h deleted file mode 100644 index 0a0b0116..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_raw_success.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneRawSuccess : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - string_t string_info; - static void ok_callback(void* context); -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read.cpp b/applications/lfrfid/scene/lfrfid_app_scene_read.cpp deleted file mode 100644 index 120eb1a0..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_read.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "lfrfid_app_scene_read.h" -#include - -static void lfrfid_read_callback(LFRFIDWorkerReadResult result, ProtocolId protocol, void* ctx) { - LfRfidApp* app = static_cast(ctx); - LfRfidApp::Event event; - - switch(result) { - case LFRFIDWorkerReadSenseStart: - event.type = LfRfidApp::EventType::ReadEventSenseStart; - break; - case LFRFIDWorkerReadSenseEnd: - event.type = LfRfidApp::EventType::ReadEventSenseEnd; - break; - case LFRFIDWorkerReadSenseCardStart: - event.type = LfRfidApp::EventType::ReadEventSenseCardStart; - break; - case LFRFIDWorkerReadSenseCardEnd: - event.type = LfRfidApp::EventType::ReadEventSenseCardEnd; - break; - case LFRFIDWorkerReadDone: - event.type = LfRfidApp::EventType::ReadEventDone; - break; - case LFRFIDWorkerReadStartASK: - event.type = LfRfidApp::EventType::ReadEventStartASK; - break; - case LFRFIDWorkerReadStartPSK: - event.type = LfRfidApp::EventType::ReadEventStartPSK; - break; - } - - event.payload.signed_int = protocol; - - app->view_controller.send_event(&event); -} - -void LfRfidAppSceneRead::on_enter(LfRfidApp* app, bool /* need_restore */) { - auto popup = app->view_controller.get(); - - DOLPHIN_DEED(DolphinDeedRfidRead); - if(app->read_type == LFRFIDWorkerReadTypePSKOnly) { - popup->set_header("Reading\nLF RFID\nPSK", 89, 30, AlignCenter, AlignTop); - } else { - popup->set_header("Reading\nLF RFID\nASK", 89, 30, AlignCenter, AlignTop); - } - - popup->set_icon(0, 3, &I_RFIDDolphinReceive_97x61); - - app->view_controller.switch_to(); - lfrfid_worker_start_thread(app->lfworker); - lfrfid_worker_read_start(app->lfworker, app->read_type, lfrfid_read_callback, app); - - notification_message(app->notification, &sequence_blink_start_cyan); -} - -bool LfRfidAppSceneRead::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = true; - auto popup = app->view_controller.get(); - - switch(event->type) { - case LfRfidApp::EventType::ReadEventSenseStart: - notification_message(app->notification, &sequence_blink_stop); - notification_message(app->notification, &sequence_blink_start_yellow); - break; - case LfRfidApp::EventType::ReadEventSenseCardStart: - notification_message(app->notification, &sequence_blink_stop); - notification_message(app->notification, &sequence_blink_start_green); - break; - case LfRfidApp::EventType::ReadEventSenseEnd: - case LfRfidApp::EventType::ReadEventSenseCardEnd: - notification_message(app->notification, &sequence_blink_stop); - notification_message(app->notification, &sequence_blink_start_cyan); - break; - case LfRfidApp::EventType::ReadEventDone: - app->protocol_id = event->payload.signed_int; - DOLPHIN_DEED(DolphinDeedRfidReadSuccess); - notification_message(app->notification, &sequence_success); - string_reset(app->file_name); - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadSuccess); - break; - case LfRfidApp::EventType::ReadEventStartPSK: - popup->set_header("Reading\nLF RFID\nPSK", 89, 30, AlignCenter, AlignTop); - break; - case LfRfidApp::EventType::ReadEventStartASK: - popup->set_header("Reading\nLF RFID\nASK", 89, 30, AlignCenter, AlignTop); - break; - default: - consumed = false; - break; - } - - return consumed; -} - -void LfRfidAppSceneRead::on_exit(LfRfidApp* app) { - notification_message(app->notification, &sequence_blink_stop); - app->view_controller.get()->clean(); - lfrfid_worker_stop(app->lfworker); - lfrfid_worker_stop_thread(app->lfworker); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read.h b/applications/lfrfid/scene/lfrfid_app_scene_read.h deleted file mode 100644 index b5035b72..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_read.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneRead : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read_menu.cpp b/applications/lfrfid/scene/lfrfid_app_scene_read_menu.cpp deleted file mode 100644 index aa3b3f1f..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_read_menu.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "lfrfid_app_scene_read_menu.h" - -typedef enum { - SubmenuSave, - SubmenuEmulate, - SubmenuWrite, -} SubmenuIndex; - -void LfRfidAppSceneReadKeyMenu::on_enter(LfRfidApp* app, bool need_restore) { - auto submenu = app->view_controller.get(); - - submenu->add_item("Save", SubmenuSave, submenu_callback, app); - submenu->add_item("Emulate", SubmenuEmulate, submenu_callback, app); - submenu->add_item("Write", SubmenuWrite, submenu_callback, app); - - if(need_restore) { - submenu->set_selected_item(submenu_item_selected); - } - - app->view_controller.switch_to(); -} - -bool LfRfidAppSceneReadKeyMenu::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::MenuSelected) { - submenu_item_selected = event->payload.signed_int; - switch(event->payload.signed_int) { - case SubmenuWrite: - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Write); - break; - case SubmenuSave: - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveName); - break; - case SubmenuEmulate: - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Emulate); - break; - } - consumed = true; - } else if(event->type == LfRfidApp::EventType::Back) { - app->scene_controller.switch_to_previous_scene(); - consumed = true; - } - - return consumed; -} - -void LfRfidAppSceneReadKeyMenu::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); -} - -void LfRfidAppSceneReadKeyMenu::submenu_callback(void* context, uint32_t index) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - - event.type = LfRfidApp::EventType::MenuSelected; - event.payload.signed_int = index; - - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read_menu.h b/applications/lfrfid/scene/lfrfid_app_scene_read_menu.h deleted file mode 100644 index 2b50b96f..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_read_menu.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneReadKeyMenu : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void submenu_callback(void* context, uint32_t index); - uint32_t submenu_item_selected = 0; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_read_success.cpp deleted file mode 100644 index 277b43a3..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_read_success.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "lfrfid_app_scene_read_success.h" -#include "../view/elements/button_element.h" -#include "../view/elements/icon_element.h" -#include "../view/elements/string_element.h" - -void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) { - string_init(string_info); - string_init(string_header); - - string_init_printf( - string_header, - "%s[%s]", - protocol_dict_get_name(app->dict, app->protocol_id), - protocol_dict_get_manufacturer(app->dict, app->protocol_id)); - - size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); - uint8_t* data = (uint8_t*)malloc(size); - protocol_dict_get_data(app->dict, app->protocol_id, data, size); - for(uint8_t i = 0; i < size; i++) { - if(i != 0) { - string_cat_printf(string_info, " "); - } - - if(i >= 9) { - string_cat_printf(string_info, "..."); - break; - } else { - string_cat_printf(string_info, "%02X", data[i]); - } - } - free(data); - - string_t render_data; - string_init(render_data); - protocol_dict_render_brief_data(app->dict, render_data, app->protocol_id); - string_cat_printf(string_info, "\r\n%s", string_get_cstr(render_data)); - string_clear(render_data); - - auto container = app->view_controller.get(); - - auto button = container->add(); - button->set_type(ButtonElement::Type::Left, "Retry"); - button->set_callback(app, LfRfidAppSceneReadSuccess::back_callback); - - button = container->add(); - button->set_type(ButtonElement::Type::Right, "More"); - button->set_callback(app, LfRfidAppSceneReadSuccess::more_callback); - - auto header = container->add(); - header->set_text(string_get_cstr(string_header), 0, 2, 0, AlignLeft, AlignTop, FontPrimary); - - auto text = container->add(); - text->set_text(string_get_cstr(string_info), 0, 16, 0, AlignLeft, AlignTop, FontSecondary); - - app->view_controller.switch_to(); - - notification_message_block(app->notification, &sequence_set_green_255); -} - -bool LfRfidAppSceneReadSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::Next) { - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadKeyMenu); - consumed = true; - } else if(event->type == LfRfidApp::EventType::Retry) { - app->scene_controller.switch_to_next_scene({LfRfidApp::SceneType::RetryConfirm}); - consumed = true; - } else if(event->type == LfRfidApp::EventType::Back) { - app->scene_controller.switch_to_next_scene({LfRfidApp::SceneType::ExitConfirm}); - consumed = true; - } - - return consumed; -} - -void LfRfidAppSceneReadSuccess::on_exit(LfRfidApp* app) { - notification_message_block(app->notification, &sequence_reset_green); - app->view_controller.get()->clean(); - string_clear(string_info); - string_clear(string_header); -} - -void LfRfidAppSceneReadSuccess::back_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Retry; - app->view_controller.send_event(&event); -} - -void LfRfidAppSceneReadSuccess::more_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Next; - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read_success.h b/applications/lfrfid/scene/lfrfid_app_scene_read_success.h deleted file mode 100644 index 6d90f631..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_read_success.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneReadSuccess : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void back_callback(void* context); - static void more_callback(void* context); - - string_t string_header; - string_t string_info; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp b/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp deleted file mode 100644 index c1812232..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "lfrfid_app_scene_retry_confirm.h" -#include "../view/elements/button_element.h" -#include "../view/elements/icon_element.h" -#include "../view/elements/string_element.h" - -void LfRfidAppSceneRetryConfirm::on_enter(LfRfidApp* app, bool /* need_restore */) { - auto container = app->view_controller.get(); - - auto button = container->add(); - button->set_type(ButtonElement::Type::Left, "Exit"); - button->set_callback(app, LfRfidAppSceneRetryConfirm::exit_callback); - - button = container->add(); - button->set_type(ButtonElement::Type::Right, "Stay"); - button->set_callback(app, LfRfidAppSceneRetryConfirm::stay_callback); - - auto line_1 = container->add(); - auto line_2 = container->add(); - - line_1->set_text("Return to Reading?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary); - line_2->set_text( - "All unsaved data will be lost!", 64, 29, 0, AlignCenter, AlignBottom, FontSecondary); - - app->view_controller.switch_to(); -} - -bool LfRfidAppSceneRetryConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::Next) { - app->scene_controller.search_and_switch_to_previous_scene({LfRfidApp::SceneType::Read}); - consumed = true; - } else if(event->type == LfRfidApp::EventType::Stay) { - app->scene_controller.switch_to_previous_scene(); - consumed = true; - } else if(event->type == LfRfidApp::EventType::Back) { - consumed = true; - } - - return consumed; -} - -void LfRfidAppSceneRetryConfirm::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); -} - -void LfRfidAppSceneRetryConfirm::exit_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Next; - app->view_controller.send_event(&event); -} - -void LfRfidAppSceneRetryConfirm::stay_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Stay; - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.h b/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.h deleted file mode 100644 index 01b7329c..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneRetryConfirm : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void exit_callback(void* context); - static void stay_callback(void* context); -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp b/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp deleted file mode 100644 index c2e5ec2a..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "lfrfid_app_scene_rpc.h" -#include -#include -#include - -void LfRfidAppSceneRpc::on_enter(LfRfidApp* app, bool /* need_restore */) { - auto popup = app->view_controller.get(); - - popup->set_header("LF RFID", 89, 42, AlignCenter, AlignBottom); - popup->set_text("RPC mode", 89, 44, AlignCenter, AlignTop); - popup->set_icon(0, 12, &I_RFIDDolphinSend_97x61); - - app->view_controller.switch_to(); - - notification_message(app->notification, &sequence_display_backlight_on); -} - -bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - UNUSED(app); - UNUSED(event); - bool consumed = false; - - if(event->type == LfRfidApp::EventType::Exit) { - consumed = true; - LfRfidApp::Event view_event; - view_event.type = LfRfidApp::EventType::Back; - app->view_controller.send_event(&view_event); - rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true); - } else if(event->type == LfRfidApp::EventType::RpcSessionClose) { - consumed = true; - LfRfidApp::Event view_event; - view_event.type = LfRfidApp::EventType::Back; - app->view_controller.send_event(&view_event); - } else if(event->type == LfRfidApp::EventType::RpcLoadFile) { - const char* arg = rpc_system_app_get_data(app->rpc_ctx); - consumed = true; - bool result = false; - if(arg && !emulating) { - string_set_str(app->file_path, arg); - if(app->load_key_data(app->file_path, false)) { - lfrfid_worker_start_thread(app->lfworker); - lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id); - emulating = true; - - auto popup = app->view_controller.get(); - app->text_store.set("emulating\n%s", string_get_cstr(app->file_name)); - popup->set_text(app->text_store.text, 89, 44, AlignCenter, AlignTop); - - notification_message(app->notification, &sequence_blink_start_magenta); - result = true; - } - } - rpc_system_app_confirm(app->rpc_ctx, RpcAppEventLoadFile, result); - } - - return consumed; -} - -void LfRfidAppSceneRpc::on_exit(LfRfidApp* app) { - if(emulating) { - lfrfid_worker_stop(app->lfworker); - lfrfid_worker_stop_thread(app->lfworker); - notification_message(app->notification, &sequence_blink_stop); - } - app->view_controller.get()->clean(); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_rpc.h b/applications/lfrfid/scene/lfrfid_app_scene_rpc.h deleted file mode 100644 index f630dfd3..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_rpc.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneRpc : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - bool emulating = false; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_data.cpp b/applications/lfrfid/scene/lfrfid_app_scene_save_data.cpp deleted file mode 100644 index c506cd72..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_data.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "lfrfid_app_scene_save_data.h" -#include - -void LfRfidAppSceneSaveData::on_enter(LfRfidApp* app, bool need_restore) { - auto byte_input = app->view_controller.get(); - size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); - - if(need_restore) { - protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size); - } else { - protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size); - } - - protocol_dict_get_data(app->dict, app->protocol_id, app->new_key_data, size); - - byte_input->set_header_text("Enter the data in hex"); - - byte_input->set_result_callback(save_callback, NULL, app, app->new_key_data, size); - - app->view_controller.switch_to(); -} - -bool LfRfidAppSceneSaveData::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::Next) { - size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); - protocol_dict_set_data(app->dict, app->protocol_id, app->new_key_data, size); - DOLPHIN_DEED(DolphinDeedRfidAdd); - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveName); - } - - return consumed; -} - -void LfRfidAppSceneSaveData::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); -} - -void LfRfidAppSceneSaveData::save_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Next; - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_data.h b/applications/lfrfid/scene/lfrfid_app_scene_save_data.h deleted file mode 100644 index d03cae12..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_data.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneSaveData : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void save_callback(void* context); -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp b/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp deleted file mode 100644 index ed58b645..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "lfrfid_app_scene_save_name.h" -#include "m-string.h" -#include -#include - -void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool /* need_restore */) { - const char* key_name = string_get_cstr(app->file_name); - - bool key_name_empty = (string_size(app->file_name) == 0); - if(key_name_empty) { - string_set_str(app->file_path, app->app_folder); - set_random_name(app->text_store.text, app->text_store.text_size); - } else { - app->text_store.set("%s", key_name); - } - - auto text_input = app->view_controller.get(); - text_input->set_header_text("Name the card"); - - text_input->set_result_callback( - save_callback, app, app->text_store.text, LFRFID_KEY_NAME_SIZE, key_name_empty); - - string_t folder_path; - string_init(folder_path); - - path_extract_dirname(string_get_cstr(app->file_path), folder_path); - - ValidatorIsFile* validator_is_file = - validator_is_file_alloc_init(string_get_cstr(folder_path), app->app_extension, key_name); - text_input->set_validator(validator_is_file_callback, validator_is_file); - - string_clear(folder_path); - - app->view_controller.switch_to(); -} - -bool LfRfidAppSceneSaveName::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::Next) { - if(string_size(app->file_name) > 0) { - app->delete_key(); - } - - string_set_str(app->file_name, app->text_store.text); - - if(app->save_key()) { - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveSuccess); - } else { - app->scene_controller.search_and_switch_to_previous_scene( - {LfRfidApp::SceneType::ReadKeyMenu}); - } - } - - return consumed; -} - -void LfRfidAppSceneSaveName::on_exit(LfRfidApp* app) { - void* validator_context = - app->view_controller.get()->get_validator_callback_context(); - app->view_controller.get()->set_validator(NULL, NULL); - validator_is_file_free((ValidatorIsFile*)validator_context); - - app->view_controller.get()->clean(); -} - -void LfRfidAppSceneSaveName::save_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Next; - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_name.h b/applications/lfrfid/scene/lfrfid_app_scene_save_name.h deleted file mode 100644 index ced42cc0..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_name.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneSaveName : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void save_callback(void* context); -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_save_success.cpp deleted file mode 100644 index 64efafa7..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_success.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "lfrfid_app_scene_save_success.h" -#include -#include -#include - -void LfRfidAppSceneSaveSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) { - auto popup = app->view_controller.get(); - - DOLPHIN_DEED(DolphinDeedRfidSave); - popup->set_icon(32, 5, &I_DolphinNice_96x59); - popup->set_header("Saved!", 5, 7, AlignLeft, AlignTop); - popup->set_context(app); - popup->set_callback(LfRfidAppSceneSaveSuccess::timeout_callback); - popup->set_timeout(1500); - popup->enable_timeout(); - - app->view_controller.switch_to(); -} - -bool LfRfidAppSceneSaveSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::Back) { - bool result = app->scene_controller.has_previous_scene( - {LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey}); - - if(result) { - app->scene_controller.search_and_switch_to_previous_scene( - {LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey}); - } else { - app->scene_controller.search_and_switch_to_another_scene( - {LfRfidApp::SceneType::SaveType}, LfRfidApp::SceneType::SelectKey); - } - - consumed = true; - } - - return consumed; -} - -void LfRfidAppSceneSaveSuccess::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); -} - -void LfRfidAppSceneSaveSuccess::timeout_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Back; - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_success.h b/applications/lfrfid/scene/lfrfid_app_scene_save_success.h deleted file mode 100644 index 62273a76..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_success.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneSaveSuccess : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void timeout_callback(void* context); -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_type.cpp b/applications/lfrfid/scene/lfrfid_app_scene_save_type.cpp deleted file mode 100644 index b017e7b0..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_type.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "lfrfid_app_scene_save_type.h" - -void LfRfidAppSceneSaveType::on_enter(LfRfidApp* app, bool need_restore) { - auto submenu = app->view_controller.get(); - - for(uint8_t i = 0; i < keys_count; i++) { - string_init_printf( - submenu_name[i], - "%s %s", - protocol_dict_get_manufacturer(app->dict, i), - protocol_dict_get_name(app->dict, i)); - submenu->add_item(string_get_cstr(submenu_name[i]), i, submenu_callback, app); - } - - if(need_restore) { - submenu->set_selected_item(submenu_item_selected); - } - - app->view_controller.switch_to(); - - // clear key name - string_reset(app->file_name); -} - -bool LfRfidAppSceneSaveType::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::MenuSelected) { - submenu_item_selected = event->payload.signed_int; - app->protocol_id = event->payload.signed_int; - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveData); - consumed = true; - } - - return consumed; -} - -void LfRfidAppSceneSaveType::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); - for(uint8_t i = 0; i < keys_count; i++) { - string_clear(submenu_name[i]); - } -} - -void LfRfidAppSceneSaveType::submenu_callback(void* context, uint32_t index) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - - event.type = LfRfidApp::EventType::MenuSelected; - event.payload.signed_int = index; - - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_type.h b/applications/lfrfid/scene/lfrfid_app_scene_save_type.h deleted file mode 100644 index e4c1be3e..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_type.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneSaveType : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void submenu_callback(void* context, uint32_t index); - uint32_t submenu_item_selected = 0; - static const uint8_t keys_count = static_cast(LFRFIDProtocol::LFRFIDProtocolMax); - string_t submenu_name[keys_count]; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_saved_info.cpp b/applications/lfrfid/scene/lfrfid_app_scene_saved_info.cpp deleted file mode 100644 index 614dd505..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_saved_info.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "lfrfid_app_scene_saved_info.h" -#include "../view/elements/button_element.h" -#include "../view/elements/icon_element.h" -#include "../view/elements/string_element.h" - -void LfRfidAppSceneSavedInfo::on_enter(LfRfidApp* app, bool /* need_restore */) { - string_init(string_info); - - string_printf( - string_info, - "%s [%s]\r\n", - string_get_cstr(app->file_name), - protocol_dict_get_name(app->dict, app->protocol_id)); - - size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); - uint8_t* data = (uint8_t*)malloc(size); - protocol_dict_get_data(app->dict, app->protocol_id, data, size); - for(uint8_t i = 0; i < size; i++) { - if(i != 0) { - string_cat_printf(string_info, " "); - } - - string_cat_printf(string_info, "%02X", data[i]); - } - free(data); - - string_t render_data; - string_init(render_data); - protocol_dict_render_data(app->dict, render_data, app->protocol_id); - string_cat_printf(string_info, "\r\n%s", string_get_cstr(render_data)); - string_clear(render_data); - - auto container = app->view_controller.get(); - - auto line_1 = container->add(); - line_1->set_text(string_get_cstr(string_info), 0, 1, 0, AlignLeft, AlignTop, FontSecondary); - - app->view_controller.switch_to(); -} - -bool LfRfidAppSceneSavedInfo::on_event(LfRfidApp* /* app */, LfRfidApp::Event* /* event */) { - return false; -} - -void LfRfidAppSceneSavedInfo::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); - string_clear(string_info); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_saved_info.h b/applications/lfrfid/scene/lfrfid_app_scene_saved_info.h deleted file mode 100644 index b0b588bc..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_saved_info.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneSavedInfo : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - string_t string_info; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.cpp b/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.cpp deleted file mode 100644 index e7a38d8a..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "lfrfid_app_scene_saved_key_menu.h" - -typedef enum { - SubmenuEmulate, - SubmenuWrite, - SubmenuEdit, - SubmenuDelete, - SubmenuInfo, -} SubmenuIndex; - -void LfRfidAppSceneSavedKeyMenu::on_enter(LfRfidApp* app, bool need_restore) { - auto submenu = app->view_controller.get(); - - submenu->add_item("Emulate", SubmenuEmulate, submenu_callback, app); - submenu->add_item("Write", SubmenuWrite, submenu_callback, app); - submenu->add_item("Edit", SubmenuEdit, submenu_callback, app); - submenu->add_item("Delete", SubmenuDelete, submenu_callback, app); - submenu->add_item("Info", SubmenuInfo, submenu_callback, app); - - if(need_restore) { - submenu->set_selected_item(submenu_item_selected); - } - - app->view_controller.switch_to(); -} - -bool LfRfidAppSceneSavedKeyMenu::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::MenuSelected) { - submenu_item_selected = event->payload.signed_int; - switch(event->payload.signed_int) { - case SubmenuEmulate: - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Emulate); - break; - case SubmenuWrite: - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Write); - break; - case SubmenuEdit: - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveData); - break; - case SubmenuDelete: - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::DeleteConfirm); - break; - case SubmenuInfo: - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SavedInfo); - break; - } - consumed = true; - } - - return consumed; -} - -void LfRfidAppSceneSavedKeyMenu::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); -} - -void LfRfidAppSceneSavedKeyMenu::submenu_callback(void* context, uint32_t index) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - - event.type = LfRfidApp::EventType::MenuSelected; - event.payload.signed_int = index; - - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.h b/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.h deleted file mode 100644 index 69a6e5e5..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneSavedKeyMenu : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void submenu_callback(void* context, uint32_t index); - uint32_t submenu_item_selected = 0; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_select_key.cpp b/applications/lfrfid/scene/lfrfid_app_scene_select_key.cpp deleted file mode 100644 index 6d5df73c..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_select_key.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "lfrfid_app_scene_select_key.h" - -void LfRfidAppSceneSelectKey::on_enter(LfRfidApp* app, bool need_restore) { - if(app->load_key_from_file_select(need_restore)) { - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SavedKeyMenu); - } else { - app->scene_controller.switch_to_previous_scene(); - } -} - -bool LfRfidAppSceneSelectKey::on_event(LfRfidApp* /* app */, LfRfidApp::Event* /* event */) { - return false; -} - -void LfRfidAppSceneSelectKey::on_exit(LfRfidApp* /* app */) { -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_select_key.h b/applications/lfrfid/scene/lfrfid_app_scene_select_key.h deleted file mode 100644 index be565a91..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_select_key.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneSelectKey : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_start.cpp b/applications/lfrfid/scene/lfrfid_app_scene_start.cpp deleted file mode 100644 index 5005c9af..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_start.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "lfrfid_app_scene_start.h" - -typedef enum { - SubmenuRead, - SubmenuSaved, - SubmenuAddManually, - SubmenuExtraActions, -} SubmenuIndex; - -void LfRfidAppSceneStart::on_enter(LfRfidApp* app, bool need_restore) { - auto submenu = app->view_controller.get(); - - submenu->add_item("Read", SubmenuRead, submenu_callback, app); - submenu->add_item("Saved", SubmenuSaved, submenu_callback, app); - submenu->add_item("Add Manually", SubmenuAddManually, submenu_callback, app); - submenu->add_item("Extra Actions", SubmenuExtraActions, submenu_callback, app); - - if(need_restore) { - submenu->set_selected_item(submenu_item_selected); - } - - app->view_controller.switch_to(); - - // clear key - string_reset(app->file_name); - app->protocol_id = PROTOCOL_NO; - app->read_type = LFRFIDWorkerReadTypeAuto; -} - -bool LfRfidAppSceneStart::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::MenuSelected) { - submenu_item_selected = event->payload.signed_int; - switch(event->payload.signed_int) { - case SubmenuRead: - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Read); - break; - case SubmenuSaved: - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SelectKey); - break; - case SubmenuAddManually: - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveType); - break; - case SubmenuExtraActions: - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ExtraActions); - break; - } - consumed = true; - } - - return consumed; -} - -void LfRfidAppSceneStart::on_exit(LfRfidApp* app) { - app->view_controller.get()->clean(); -} - -void LfRfidAppSceneStart::submenu_callback(void* context, uint32_t index) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - - event.type = LfRfidApp::EventType::MenuSelected; - event.payload.signed_int = index; - - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_start.h b/applications/lfrfid/scene/lfrfid_app_scene_start.h deleted file mode 100644 index 255590d6..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_start.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneStart : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void submenu_callback(void* context, uint32_t index); - uint32_t submenu_item_selected = 0; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_write.cpp b/applications/lfrfid/scene/lfrfid_app_scene_write.cpp deleted file mode 100644 index 39e0630e..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_write.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "lfrfid_app_scene_write.h" - -static void lfrfid_write_callback(LFRFIDWorkerWriteResult result, void* ctx) { - LfRfidApp* app = static_cast(ctx); - LfRfidApp::Event event; - - switch(result) { - case LFRFIDWorkerWriteOK: - event.type = LfRfidApp::EventType::WriteEventOK; - break; - case LFRFIDWorkerWriteProtocolCannotBeWritten: - event.type = LfRfidApp::EventType::WriteEventProtocolCannotBeWritten; - break; - case LFRFIDWorkerWriteFobCannotBeWritten: - event.type = LfRfidApp::EventType::WriteEventFobCannotBeWritten; - break; - case LFRFIDWorkerWriteTooLongToWrite: - event.type = LfRfidApp::EventType::WriteEventTooLongToWrite; - break; - } - - app->view_controller.send_event(&event); -} - -void LfRfidAppSceneWrite::on_enter(LfRfidApp* app, bool /* need_restore */) { - auto popup = app->view_controller.get(); - - popup->set_header("Writing", 89, 30, AlignCenter, AlignTop); - if(string_size(app->file_name)) { - popup->set_text(string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop); - } else { - popup->set_text( - protocol_dict_get_name(app->dict, app->protocol_id), 89, 43, AlignCenter, AlignTop); - } - popup->set_icon(0, 3, &I_RFIDDolphinSend_97x61); - - app->view_controller.switch_to(); - - size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); - app->old_key_data = (uint8_t*)malloc(size); - protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size); - - lfrfid_worker_start_thread(app->lfworker); - lfrfid_worker_write_start( - app->lfworker, (LFRFIDProtocol)app->protocol_id, lfrfid_write_callback, app); - notification_message(app->notification, &sequence_blink_start_magenta); -} - -bool LfRfidAppSceneWrite::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = true; - auto popup = app->view_controller.get(); - - switch(event->type) { - case LfRfidApp::EventType::WriteEventOK: - notification_message(app->notification, &sequence_success); - app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::WriteSuccess); - break; - case LfRfidApp::EventType::WriteEventProtocolCannotBeWritten: - popup->set_icon(72, 17, &I_DolphinCommon_56x48); - popup->set_header("Error", 64, 3, AlignCenter, AlignTop); - popup->set_text("This protocol\ncannot be written", 3, 17, AlignLeft, AlignTop); - notification_message(app->notification, &sequence_blink_start_red); - break; - case LfRfidApp::EventType::WriteEventFobCannotBeWritten: - case LfRfidApp::EventType::WriteEventTooLongToWrite: - popup->set_icon(72, 17, &I_DolphinCommon_56x48); - popup->set_header("Still trying to write...", 64, 3, AlignCenter, AlignTop); - popup->set_text( - "Make sure this\ncard is writable\nand not\nprotected.", 3, 17, AlignLeft, AlignTop); - notification_message(app->notification, &sequence_blink_start_yellow); - break; - default: - consumed = false; - } - - return consumed; -} - -void LfRfidAppSceneWrite::on_exit(LfRfidApp* app) { - notification_message(app->notification, &sequence_blink_stop); - app->view_controller.get()->clean(); - lfrfid_worker_stop(app->lfworker); - lfrfid_worker_stop_thread(app->lfworker); - - size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); - protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size); - free(app->old_key_data); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_write.h b/applications/lfrfid/scene/lfrfid_app_scene_write.h deleted file mode 100644 index 7564eff9..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_write.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneWrite : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; -}; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_write_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_write_success.cpp deleted file mode 100644 index 3cf00183..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_write_success.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "lfrfid_app_scene_write_success.h" - -void LfRfidAppSceneWriteSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) { - auto popup = app->view_controller.get(); - popup->set_header("Successfully\nwritten!", 94, 3, AlignCenter, AlignTop); - popup->set_icon(0, 6, &I_RFIDDolphinSuccess_108x57); - popup->set_context(app); - popup->set_callback(LfRfidAppSceneWriteSuccess::timeout_callback); - popup->set_timeout(1500); - popup->enable_timeout(); - - app->view_controller.switch_to(); - notification_message_block(app->notification, &sequence_set_green_255); -} - -bool LfRfidAppSceneWriteSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidApp::EventType::Back) { - app->scene_controller.search_and_switch_to_previous_scene( - {LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey}); - consumed = true; - } - - return consumed; -} - -void LfRfidAppSceneWriteSuccess::on_exit(LfRfidApp* app) { - notification_message_block(app->notification, &sequence_reset_green); - app->view_controller.get()->clean(); -} - -void LfRfidAppSceneWriteSuccess::timeout_callback(void* context) { - LfRfidApp* app = static_cast(context); - LfRfidApp::Event event; - event.type = LfRfidApp::EventType::Back; - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid/scene/lfrfid_app_scene_write_success.h b/applications/lfrfid/scene/lfrfid_app_scene_write_success.h deleted file mode 100644 index 4ac9f089..00000000 --- a/applications/lfrfid/scene/lfrfid_app_scene_write_success.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "../lfrfid_app.h" - -class LfRfidAppSceneWriteSuccess : public GenericScene { -public: - void on_enter(LfRfidApp* app, bool need_restore) final; - bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; - void on_exit(LfRfidApp* app) final; - -private: - static void timeout_callback(void* context); -}; diff --git a/applications/lfrfid/view/container_vm.cpp b/applications/lfrfid/view/container_vm.cpp deleted file mode 100644 index 3c01ba30..00000000 --- a/applications/lfrfid/view/container_vm.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include "container_vm.h" -#include "elements/generic_element.h" -#include "elements/string_element.h" -#include "elements/icon_element.h" -#include "elements/button_element.h" -#include - -class ContainerVMData { -public: - ContainerVMData(){}; - - ~ContainerVMData() { - for(auto& it : elements) delete it; - }; - - std::list elements; - - template T add(const T element, View* view) { - elements.push_back(element); - element->set_parent_view(view); - return element; - } - - void clean() { - for(auto& it : elements) delete it; - elements.clear(); - } -}; - -struct ContainerVMModel { - ContainerVMData* data; -}; - -ContainerVM::ContainerVM() { - view = view_alloc(); - view_set_context(view, this); - view_allocate_model(view, ViewModelTypeLocking, sizeof(ContainerVMModel)); - - with_view_model_cpp(view, ContainerVMModel, model, { - model->data = new ContainerVMData(); - return true; - }); - - view_set_draw_callback(view, view_draw_callback); - view_set_input_callback(view, view_input_callback); -} - -ContainerVM::~ContainerVM() { - with_view_model_cpp(view, ContainerVMModel, model, { - delete model->data; - model->data = NULL; - return false; - }); - - view_free(view); -} - -View* ContainerVM::get_view() { - return view; -} - -void ContainerVM::clean() { - with_view_model_cpp(view, ContainerVMModel, model, { - model->data->clean(); - return true; - }); -} - -template T* ContainerVM::add() { - T* element = new T(); - - with_view_model_cpp(view, ContainerVMModel, model, { - model->data->add(element, view); - return true; - }); - - return element; -} - -void ContainerVM::view_draw_callback(Canvas* canvas, void* model) { - ContainerVMData* data = static_cast(model)->data; - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - - for(const auto& element : data->elements) { - element->draw(canvas); - } -} - -bool ContainerVM::view_input_callback(InputEvent* event, void* context) { - bool consumed = false; - View* view = static_cast(context)->view; - - with_view_model_cpp(view, ContainerVMModel, model, { - for(const auto& element : model->data->elements) { - if(element->input(event)) { - consumed = true; - } - - if(consumed) { - break; - } - } - - return consumed; - }); - - return consumed; -} - -template StringElement* ContainerVM::add(); -template IconElement* ContainerVM::add(); -template ButtonElement* ContainerVM::add(); diff --git a/applications/lfrfid/view/container_vm.h b/applications/lfrfid/view/container_vm.h deleted file mode 100644 index 011baa2e..00000000 --- a/applications/lfrfid/view/container_vm.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include - -class ContainerVM : public GenericViewModule { -public: - ContainerVM(); - ~ContainerVM() final; - View* get_view() final; - void clean() final; - - template T* add(); - -private: - View* view; - static void view_draw_callback(Canvas* canvas, void* model); - static bool view_input_callback(InputEvent* event, void* context); -}; diff --git a/applications/lfrfid/view/elements/button_element.cpp b/applications/lfrfid/view/elements/button_element.cpp deleted file mode 100644 index 58e1ac3e..00000000 --- a/applications/lfrfid/view/elements/button_element.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "button_element.h" -#include - -ButtonElement::ButtonElement() { -} - -ButtonElement::~ButtonElement() { -} - -void ButtonElement::draw(Canvas* canvas) { - if(text != nullptr) { - canvas_set_font(canvas, FontSecondary); - switch(type) { - case Type::Left: - elements_button_left(canvas, text); - break; - case Type::Center: - elements_button_center(canvas, text); - break; - case Type::Right: - elements_button_right(canvas, text); - break; - } - } -} - -bool ButtonElement::input(InputEvent* event) { - bool consumed = false; - if(event->type == InputTypeShort && callback != nullptr) { - switch(type) { - case Type::Left: - if(event->key == InputKeyLeft) { - callback(context); - consumed = true; - } - break; - case Type::Center: - if(event->key == InputKeyOk) { - callback(context); - consumed = true; - } - break; - case Type::Right: - if(event->key == InputKeyRight) { - callback(context); - consumed = true; - } - break; - } - } - - return consumed; -} - -void ButtonElement::set_type(Type _type, const char* _text) { - lock_model(); - type = _type; - text = _text; - unlock_model(true); -} - -void ButtonElement::set_callback(void* _context, ButtonElementCallback _callback) { - context = _context; - callback = _callback; -} diff --git a/applications/lfrfid/view/elements/button_element.h b/applications/lfrfid/view/elements/button_element.h deleted file mode 100644 index eb964427..00000000 --- a/applications/lfrfid/view/elements/button_element.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include "generic_element.h" - -typedef void (*ButtonElementCallback)(void* context); - -class ButtonElement : public GenericElement { -public: - ButtonElement(); - ~ButtonElement() final; - void draw(Canvas* canvas) final; - bool input(InputEvent* event) final; - - enum class Type : uint8_t { - Left, - Center, - Right, - }; - - void set_type(Type type, const char* text); - void set_callback(void* context, ButtonElementCallback callback); - -private: - Type type = Type::Left; - const char* text = nullptr; - - void* context = nullptr; - ButtonElementCallback callback = nullptr; -}; diff --git a/applications/lfrfid/view/elements/generic_element.cpp b/applications/lfrfid/view/elements/generic_element.cpp deleted file mode 100644 index e0f08d15..00000000 --- a/applications/lfrfid/view/elements/generic_element.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "generic_element.h" - -void GenericElement::lock_model() { - furi_assert(view != nullptr); - view_get_model(view); -} - -void GenericElement::unlock_model(bool need_redraw) { - furi_assert(view != nullptr); - view_commit_model(view, need_redraw); -} - -void GenericElement::set_parent_view(View* _view) { - view = _view; -} diff --git a/applications/lfrfid/view/elements/generic_element.h b/applications/lfrfid/view/elements/generic_element.h deleted file mode 100644 index f5a58b2d..00000000 --- a/applications/lfrfid/view/elements/generic_element.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include -#include - -class GenericElement { -public: - GenericElement(){}; - virtual ~GenericElement(){}; - virtual void draw(Canvas* canvas) = 0; - virtual bool input(InputEvent* event) = 0; - - // TODO that must be accessible only to ContainerVMData - void set_parent_view(View* view); - - // TODO that must be accessible only to inheritors - void lock_model(); - void unlock_model(bool need_redraw); - -private: - View* view = nullptr; -}; diff --git a/applications/lfrfid/view/elements/icon_element.cpp b/applications/lfrfid/view/elements/icon_element.cpp deleted file mode 100644 index 0b6fba7d..00000000 --- a/applications/lfrfid/view/elements/icon_element.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "icon_element.h" - -IconElement::IconElement() { -} - -IconElement::~IconElement() { -} - -void IconElement::draw(Canvas* canvas) { - if(icon != NULL) { - canvas_draw_icon(canvas, x, y, icon); - } -} - -bool IconElement::input(InputEvent* /* event */) { - return false; -} - -void IconElement::set_icon(uint8_t _x, uint8_t _y, const Icon* _icon) { - lock_model(); - icon = _icon; - x = _x; - y = _y; - unlock_model(true); -} diff --git a/applications/lfrfid/view/elements/icon_element.h b/applications/lfrfid/view/elements/icon_element.h deleted file mode 100644 index a0820274..00000000 --- a/applications/lfrfid/view/elements/icon_element.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "generic_element.h" - -class IconElement : public GenericElement { -public: - IconElement(); - ~IconElement() final; - void draw(Canvas* canvas) final; - bool input(InputEvent* event) final; - - void set_icon(uint8_t x = 0, uint8_t y = 0, const Icon* icon = NULL); - -private: - const Icon* icon = NULL; - uint8_t x = 0; - uint8_t y = 0; -}; diff --git a/applications/lfrfid/view/elements/string_element.cpp b/applications/lfrfid/view/elements/string_element.cpp deleted file mode 100644 index 44c11e01..00000000 --- a/applications/lfrfid/view/elements/string_element.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "string_element.h" -#include - -StringElement::StringElement() { -} - -StringElement::~StringElement() { -} - -void StringElement::draw(Canvas* canvas) { - if(text) { - string_t line; - string_init(line); - string_set_str(line, text); - - canvas_set_font(canvas, font); - if(fit_width != 0) { - elements_string_fit_width(canvas, line, fit_width); - } - elements_multiline_text_aligned(canvas, x, y, horizontal, vertical, string_get_cstr(line)); - - string_clear(line); - } -} - -bool StringElement::input(InputEvent* /* event */) { - return false; -} - -void StringElement::set_text( - const char* _text, - uint8_t _x, - uint8_t _y, - uint8_t _fit_w, - Align _horizontal, - Align _vertical, - Font _font) { - lock_model(); - text = _text; - x = _x; - y = _y; - fit_width = _fit_w; - horizontal = _horizontal; - vertical = _vertical; - font = _font; - unlock_model(true); -} diff --git a/applications/lfrfid/view/elements/string_element.h b/applications/lfrfid/view/elements/string_element.h deleted file mode 100644 index 173fdd60..00000000 --- a/applications/lfrfid/view/elements/string_element.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include "generic_element.h" - -class StringElement : public GenericElement { -public: - StringElement(); - ~StringElement() final; - void draw(Canvas* canvas) final; - bool input(InputEvent* event) final; - - void set_text( - const char* text = NULL, - uint8_t x = 0, - uint8_t y = 0, - uint8_t fit_width = 0, - Align horizontal = AlignLeft, - Align vertical = AlignTop, - Font font = FontPrimary); - -private: - const char* text = NULL; - uint8_t x = 0; - uint8_t y = 0; - uint8_t fit_width = 0; - Align horizontal = AlignLeft; - Align vertical = AlignTop; - Font font = FontPrimary; -}; diff --git a/applications/lfrfid_debug/lfrfid_debug_app.cpp b/applications/lfrfid_debug/lfrfid_debug_app.cpp deleted file mode 100644 index ef970e36..00000000 --- a/applications/lfrfid_debug/lfrfid_debug_app.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "lfrfid_debug_app.h" -#include "scene/lfrfid_debug_app_scene_start.h" -#include "scene/lfrfid_debug_app_scene_tune.h" - -LfRfidDebugApp::LfRfidDebugApp() - : scene_controller{this} { -} - -LfRfidDebugApp::~LfRfidDebugApp() { -} - -void LfRfidDebugApp::run() { - view_controller.attach_to_gui(ViewDispatcherTypeFullscreen); - scene_controller.add_scene(SceneType::Start, new LfRfidDebugAppSceneStart()); - scene_controller.add_scene(SceneType::TuneScene, new LfRfidDebugAppSceneTune()); - scene_controller.process(100); -} diff --git a/applications/lfrfid_debug/lfrfid_debug_app.h b/applications/lfrfid_debug/lfrfid_debug_app.h deleted file mode 100644 index fee183ae..00000000 --- a/applications/lfrfid_debug/lfrfid_debug_app.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include - -#include -#include "view_modules/lfrfid_view_tune_vm.h" - -class LfRfidDebugApp { -public: - enum class EventType : uint8_t { - GENERIC_EVENT_ENUM_VALUES, - MenuSelected, - }; - - enum class SceneType : uint8_t { - GENERIC_SCENE_ENUM_VALUES, - TuneScene, - }; - - class Event { - public: - union { - int32_t menu_index; - } payload; - - EventType type; - }; - - SceneController, LfRfidDebugApp> scene_controller; - ViewController view_controller; - - ~LfRfidDebugApp(); - LfRfidDebugApp(); - - void run(); -}; diff --git a/applications/lfrfid_debug/lfrfid_debug_app_launcher.cpp b/applications/lfrfid_debug/lfrfid_debug_app_launcher.cpp deleted file mode 100644 index 4551a17c..00000000 --- a/applications/lfrfid_debug/lfrfid_debug_app_launcher.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "lfrfid_debug_app.h" - -// app enter function -extern "C" int32_t lfrfid_debug_app(void* p) { - UNUSED(p); - LfRfidDebugApp* app = new LfRfidDebugApp(); - app->run(); - delete app; - - return 0; -} diff --git a/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_start.cpp b/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_start.cpp deleted file mode 100644 index 873e152a..00000000 --- a/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_start.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "lfrfid_debug_app_scene_start.h" - -typedef enum { - SubmenuTune, -} SubmenuIndex; - -void LfRfidDebugAppSceneStart::on_enter(LfRfidDebugApp* app, bool need_restore) { - auto submenu = app->view_controller.get(); - auto callback = cbc::obtain_connector(this, &LfRfidDebugAppSceneStart::submenu_callback); - - submenu->add_item("Tune", SubmenuTune, callback, app); - - if(need_restore) { - submenu->set_selected_item(submenu_item_selected); - } - app->view_controller.switch_to(); -} - -bool LfRfidDebugAppSceneStart::on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) { - bool consumed = false; - - if(event->type == LfRfidDebugApp::EventType::MenuSelected) { - submenu_item_selected = event->payload.menu_index; - switch(event->payload.menu_index) { - case SubmenuTune: - app->scene_controller.switch_to_next_scene(LfRfidDebugApp::SceneType::TuneScene); - break; - } - consumed = true; - } - - return consumed; -} - -void LfRfidDebugAppSceneStart::on_exit(LfRfidDebugApp* app) { - app->view_controller.get()->clean(); -} - -void LfRfidDebugAppSceneStart::submenu_callback(void* context, uint32_t index) { - LfRfidDebugApp* app = static_cast(context); - LfRfidDebugApp::Event event; - - event.type = LfRfidDebugApp::EventType::MenuSelected; - event.payload.menu_index = index; - - app->view_controller.send_event(&event); -} diff --git a/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_start.h b/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_start.h deleted file mode 100644 index 7fc0b07d..00000000 --- a/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_start.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "../lfrfid_debug_app.h" - -class LfRfidDebugAppSceneStart : public GenericScene { -public: - void on_enter(LfRfidDebugApp* app, bool need_restore) final; - bool on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) final; - void on_exit(LfRfidDebugApp* app) final; - -private: - void submenu_callback(void* context, uint32_t index); - uint32_t submenu_item_selected = 0; -}; diff --git a/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.h b/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.h deleted file mode 100644 index 53399efc..00000000 --- a/applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "../lfrfid_debug_app.h" - -class LfRfidDebugAppSceneTune : public GenericScene { -public: - void on_enter(LfRfidDebugApp* app, bool need_restore) final; - bool on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) final; - void on_exit(LfRfidDebugApp* app) final; -}; diff --git a/applications/lfrfid_debug/view_modules/lfrfid_view_tune_vm.cpp b/applications/lfrfid_debug/view_modules/lfrfid_view_tune_vm.cpp deleted file mode 100644 index 5c244b92..00000000 --- a/applications/lfrfid_debug/view_modules/lfrfid_view_tune_vm.cpp +++ /dev/null @@ -1,214 +0,0 @@ -#include "lfrfid_view_tune_vm.h" -#include -#include - -struct LfRfidViewTuneVMModel { - bool dirty; - bool fine; - uint32_t ARR; - uint32_t CCR; - int pos; -}; - -void LfRfidViewTuneVM::view_draw_callback(Canvas* canvas, void* _model) { - LfRfidViewTuneVMModel* model = reinterpret_cast(_model); - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - if(model->fine) { - canvas_draw_box( - canvas, - 128 - canvas_string_width(canvas, "Fine") - 4, - 0, - canvas_string_width(canvas, "Fine") + 4, - canvas_current_font_height(canvas) + 1); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_str_aligned(canvas, 128 - 2, 2, AlignRight, AlignTop, "Fine"); - canvas_set_color(canvas, ColorBlack); - - constexpr uint8_t buffer_size = 128; - char buffer[buffer_size + 1]; - double freq = ((float)SystemCoreClock / ((float)model->ARR + 1)); - double duty = ((float)model->CCR + 1) / ((float)model->ARR + 1) * 100.0f; - snprintf( - buffer, - buffer_size, - "%sARR: %lu\n" - "freq = %.4f\n" - "%sCCR: %lu\n" - "duty = %.4f", - model->pos == 0 ? ">" : "", - model->ARR, - freq, - model->pos == 1 ? ">" : "", - model->CCR, - duty); - elements_multiline_text_aligned(canvas, 2, 2, AlignLeft, AlignTop, buffer); -} - -bool LfRfidViewTuneVM::view_input_callback(InputEvent* event, void* context) { - LfRfidViewTuneVM* _this = reinterpret_cast(context); - bool consumed = false; - - // Process key presses only - if(event->type == InputTypeShort || event->type == InputTypeRepeat) { - consumed = true; - - switch(event->key) { - case InputKeyLeft: - _this->button_left(); - break; - case InputKeyRight: - _this->button_right(); - break; - case InputKeyUp: - _this->button_up(); - break; - case InputKeyDown: - _this->button_down(); - break; - case InputKeyOk: - _this->button_ok(); - break; - default: - consumed = false; - break; - } - } - - return consumed; -} - -void LfRfidViewTuneVM::button_up() { - with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { - if(model->pos > 0) model->pos--; - return true; - }); -} - -void LfRfidViewTuneVM::button_down() { - with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { - if(model->pos < 1) model->pos++; - return true; - }); -} - -void LfRfidViewTuneVM::button_left() { - with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { - if(model->pos == 0) { - if(model->fine) { - model->ARR -= 1; - } else { - model->ARR -= 10; - } - } else if(model->pos == 1) { - if(model->fine) { - model->CCR -= 1; - } else { - model->CCR -= 10; - } - } - - model->dirty = true; - return true; - }); -} - -void LfRfidViewTuneVM::button_right() { - with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { - if(model->pos == 0) { - if(model->fine) { - model->ARR += 1; - } else { - model->ARR += 10; - } - } else if(model->pos == 1) { - if(model->fine) { - model->CCR += 1; - } else { - model->CCR += 10; - } - } - - model->dirty = true; - return true; - }); -} - -void LfRfidViewTuneVM::button_ok() { - with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { - model->fine = !model->fine; - return true; - }); -} - -LfRfidViewTuneVM::LfRfidViewTuneVM() { - view = view_alloc(); - view_set_context(view, this); - view_allocate_model(view, ViewModelTypeLocking, sizeof(LfRfidViewTuneVMModel)); - - with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { - model->dirty = true; - model->fine = false; - model->ARR = 511; - model->CCR = 255; - model->pos = 0; - return true; - }); - - view_set_draw_callback( - view, cbc::obtain_connector(this, &LfRfidViewTuneVM::view_draw_callback)); - view_set_input_callback( - view, cbc::obtain_connector(this, &LfRfidViewTuneVM::view_input_callback)); -} - -LfRfidViewTuneVM::~LfRfidViewTuneVM() { - view_free(view); -} - -View* LfRfidViewTuneVM::get_view() { - return view; -} - -void LfRfidViewTuneVM::clean() { - with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { - model->dirty = true; - model->fine = false; - model->ARR = 511; - model->CCR = 255; - model->pos = 0; - return true; - }); -} - -bool LfRfidViewTuneVM::is_dirty() { - bool result; - with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { - result = model->dirty; - model->dirty = false; - return false; - }); - - return result; -} - -uint32_t LfRfidViewTuneVM::get_ARR() { - uint32_t result; - with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { - result = model->ARR; - return false; - }); - - return result; -} - -uint32_t LfRfidViewTuneVM::get_CCR() { - uint32_t result; - with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { - result = model->CCR; - return false; - }); - - return result; -} diff --git a/applications/lfrfid_debug/view_modules/lfrfid_view_tune_vm.h b/applications/lfrfid_debug/view_modules/lfrfid_view_tune_vm.h deleted file mode 100644 index 7fb18565..00000000 --- a/applications/lfrfid_debug/view_modules/lfrfid_view_tune_vm.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include -#include - -class LfRfidViewTuneVM : public GenericViewModule { -public: - LfRfidViewTuneVM(); - ~LfRfidViewTuneVM() final; - View* get_view() final; - void clean() final; - - bool is_dirty(); - uint32_t get_ARR(); - uint32_t get_CCR(); - -private: - View* view; - void view_draw_callback(Canvas* canvas, void* _model); - bool view_input_callback(InputEvent* event, void* context); - - void button_up(); - void button_down(); - void button_left(); - void button_right(); - void button_ok(); -}; diff --git a/applications/main/application.fam b/applications/main/application.fam new file mode 100644 index 00000000..1fc30990 --- /dev/null +++ b/applications/main/application.fam @@ -0,0 +1,17 @@ +App( + appid="main_apps", + name="Basic applications for main menu", + apptype=FlipperAppType.METAPACKAGE, + provides=[ + "gpio", + "ibutton", + "infrared", + "lfrfid", + "nfc", + "subghz", + "bad_usb", + "u2f", + "fap_loader", + "archive", + ], +) diff --git a/applications/archive/application.fam b/applications/main/archive/application.fam similarity index 100% rename from applications/archive/application.fam rename to applications/main/archive/application.fam diff --git a/applications/archive/archive.c b/applications/main/archive/archive.c similarity index 100% rename from applications/archive/archive.c rename to applications/main/archive/archive.c diff --git a/applications/archive/archive.h b/applications/main/archive/archive.h similarity index 100% rename from applications/archive/archive.h rename to applications/main/archive/archive.h diff --git a/applications/archive/archive_i.h b/applications/main/archive/archive_i.h similarity index 100% rename from applications/archive/archive_i.h rename to applications/main/archive/archive_i.h diff --git a/applications/archive/helpers/archive_apps.c b/applications/main/archive/helpers/archive_apps.c similarity index 100% rename from applications/archive/helpers/archive_apps.c rename to applications/main/archive/helpers/archive_apps.c diff --git a/applications/archive/helpers/archive_apps.h b/applications/main/archive/helpers/archive_apps.h similarity index 100% rename from applications/archive/helpers/archive_apps.h rename to applications/main/archive/helpers/archive_apps.h diff --git a/applications/archive/helpers/archive_browser.c b/applications/main/archive/helpers/archive_browser.c similarity index 98% rename from applications/archive/helpers/archive_browser.c rename to applications/main/archive/helpers/archive_browser.c index 2dfb9484..00bb6b06 100644 --- a/applications/archive/helpers/archive_browser.c +++ b/applications/main/archive/helpers/archive_browser.c @@ -1,4 +1,4 @@ -#include "archive/views/archive_browser_view.h" +#include #include "archive_files.h" #include "archive_apps.h" #include "archive_browser.h" @@ -270,7 +270,7 @@ void archive_file_array_load(ArchiveBrowserView* browser, int8_t dir) { ArchiveFile_t* archive_get_current_file(ArchiveBrowserView* browser) { furi_assert(browser); - ArchiveFile_t* selected; + ArchiveFile_t* selected = NULL; with_view_model( browser->view, (ArchiveBrowserViewModel * model) { selected = files_array_size(model->files) ? @@ -284,7 +284,7 @@ ArchiveFile_t* archive_get_current_file(ArchiveBrowserView* browser) { ArchiveFile_t* archive_get_file_at(ArchiveBrowserView* browser, size_t idx) { furi_assert(browser); - ArchiveFile_t* selected; + ArchiveFile_t* selected = NULL; with_view_model( browser->view, (ArchiveBrowserViewModel * model) { @@ -298,7 +298,7 @@ ArchiveFile_t* archive_get_file_at(ArchiveBrowserView* browser, size_t idx) { ArchiveTabEnum archive_get_tab(ArchiveBrowserView* browser) { furi_assert(browser); - ArchiveTabEnum tab_id; + ArchiveTabEnum tab_id = 0; with_view_model( browser->view, (ArchiveBrowserViewModel * model) { tab_id = model->tab_idx; @@ -451,8 +451,6 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) { archive_file_browser_set_path( browser, browser->path, archive_get_tab_ext(tab), skip_assets); tab_empty = false; // Empty check will be performed later - } else { - tab_empty = true; } } diff --git a/applications/archive/helpers/archive_browser.h b/applications/main/archive/helpers/archive_browser.h similarity index 100% rename from applications/archive/helpers/archive_browser.h rename to applications/main/archive/helpers/archive_browser.h diff --git a/applications/archive/helpers/archive_favorites.c b/applications/main/archive/helpers/archive_favorites.c similarity index 100% rename from applications/archive/helpers/archive_favorites.c rename to applications/main/archive/helpers/archive_favorites.c diff --git a/applications/archive/helpers/archive_favorites.h b/applications/main/archive/helpers/archive_favorites.h similarity index 100% rename from applications/archive/helpers/archive_favorites.h rename to applications/main/archive/helpers/archive_favorites.h diff --git a/applications/archive/helpers/archive_files.c b/applications/main/archive/helpers/archive_files.c similarity index 100% rename from applications/archive/helpers/archive_files.c rename to applications/main/archive/helpers/archive_files.c diff --git a/applications/archive/helpers/archive_files.h b/applications/main/archive/helpers/archive_files.h similarity index 100% rename from applications/archive/helpers/archive_files.h rename to applications/main/archive/helpers/archive_files.h diff --git a/applications/archive/scenes/archive_scene.c b/applications/main/archive/scenes/archive_scene.c similarity index 100% rename from applications/archive/scenes/archive_scene.c rename to applications/main/archive/scenes/archive_scene.c diff --git a/applications/archive/scenes/archive_scene.h b/applications/main/archive/scenes/archive_scene.h similarity index 100% rename from applications/archive/scenes/archive_scene.h rename to applications/main/archive/scenes/archive_scene.h diff --git a/applications/archive/scenes/archive_scene_browser.c b/applications/main/archive/scenes/archive_scene_browser.c similarity index 100% rename from applications/archive/scenes/archive_scene_browser.c rename to applications/main/archive/scenes/archive_scene_browser.c diff --git a/applications/archive/scenes/archive_scene_config.h b/applications/main/archive/scenes/archive_scene_config.h similarity index 100% rename from applications/archive/scenes/archive_scene_config.h rename to applications/main/archive/scenes/archive_scene_config.h diff --git a/applications/archive/scenes/archive_scene_delete.c b/applications/main/archive/scenes/archive_scene_delete.c similarity index 100% rename from applications/archive/scenes/archive_scene_delete.c rename to applications/main/archive/scenes/archive_scene_delete.c diff --git a/applications/archive/scenes/archive_scene_rename.c b/applications/main/archive/scenes/archive_scene_rename.c similarity index 100% rename from applications/archive/scenes/archive_scene_rename.c rename to applications/main/archive/scenes/archive_scene_rename.c diff --git a/applications/archive/views/archive_browser_view.c b/applications/main/archive/views/archive_browser_view.c similarity index 99% rename from applications/archive/views/archive_browser_view.c rename to applications/main/archive/views/archive_browser_view.c index 174071ad..ddd6637d 100644 --- a/applications/archive/views/archive_browser_view.c +++ b/applications/main/archive/views/archive_browser_view.c @@ -194,7 +194,7 @@ static void archive_render_status_bar(Canvas* canvas, ArchiveBrowserViewModel* m canvas_set_color(canvas, ColorBlack); } -void archive_view_render(Canvas* canvas, void* mdl) { +static void archive_view_render(Canvas* canvas, void* mdl) { ArchiveBrowserViewModel* model = mdl; archive_render_status_bar(canvas, mdl); @@ -234,7 +234,7 @@ static bool is_file_list_load_required(ArchiveBrowserViewModel* model) { return false; } -bool archive_view_input(InputEvent* event, void* context) { +static bool archive_view_input(InputEvent* event, void* context) { furi_assert(event); furi_assert(context); diff --git a/applications/archive/views/archive_browser_view.h b/applications/main/archive/views/archive_browser_view.h similarity index 100% rename from applications/archive/views/archive_browser_view.h rename to applications/main/archive/views/archive_browser_view.h diff --git a/applications/bad_usb/application.fam b/applications/main/bad_usb/application.fam similarity index 100% rename from applications/bad_usb/application.fam rename to applications/main/bad_usb/application.fam diff --git a/applications/bad_usb/bad_usb_app.c b/applications/main/bad_usb/bad_usb_app.c similarity index 100% rename from applications/bad_usb/bad_usb_app.c rename to applications/main/bad_usb/bad_usb_app.c diff --git a/applications/bad_usb/bad_usb_app.h b/applications/main/bad_usb/bad_usb_app.h similarity index 100% rename from applications/bad_usb/bad_usb_app.h rename to applications/main/bad_usb/bad_usb_app.h diff --git a/applications/bad_usb/bad_usb_app_i.h b/applications/main/bad_usb/bad_usb_app_i.h similarity index 100% rename from applications/bad_usb/bad_usb_app_i.h rename to applications/main/bad_usb/bad_usb_app_i.h diff --git a/applications/bad_usb/bad_usb_script.c b/applications/main/bad_usb/bad_usb_script.c similarity index 100% rename from applications/bad_usb/bad_usb_script.c rename to applications/main/bad_usb/bad_usb_script.c diff --git a/applications/bad_usb/bad_usb_script.h b/applications/main/bad_usb/bad_usb_script.h similarity index 100% rename from applications/bad_usb/bad_usb_script.h rename to applications/main/bad_usb/bad_usb_script.h diff --git a/applications/bad_usb/scenes/bad_usb_scene.c b/applications/main/bad_usb/scenes/bad_usb_scene.c similarity index 100% rename from applications/bad_usb/scenes/bad_usb_scene.c rename to applications/main/bad_usb/scenes/bad_usb_scene.c diff --git a/applications/bad_usb/scenes/bad_usb_scene.h b/applications/main/bad_usb/scenes/bad_usb_scene.h similarity index 100% rename from applications/bad_usb/scenes/bad_usb_scene.h rename to applications/main/bad_usb/scenes/bad_usb_scene.h diff --git a/applications/bad_usb/scenes/bad_usb_scene_config.h b/applications/main/bad_usb/scenes/bad_usb_scene_config.h similarity index 100% rename from applications/bad_usb/scenes/bad_usb_scene_config.h rename to applications/main/bad_usb/scenes/bad_usb_scene_config.h diff --git a/applications/bad_usb/scenes/bad_usb_scene_error.c b/applications/main/bad_usb/scenes/bad_usb_scene_error.c similarity index 100% rename from applications/bad_usb/scenes/bad_usb_scene_error.c rename to applications/main/bad_usb/scenes/bad_usb_scene_error.c diff --git a/applications/bad_usb/scenes/bad_usb_scene_file_select.c b/applications/main/bad_usb/scenes/bad_usb_scene_file_select.c similarity index 80% rename from applications/bad_usb/scenes/bad_usb_scene_file_select.c rename to applications/main/bad_usb/scenes/bad_usb_scene_file_select.c index 1e6ba895..c562fc2d 100644 --- a/applications/bad_usb/scenes/bad_usb_scene_file_select.c +++ b/applications/main/bad_usb/scenes/bad_usb_scene_file_select.c @@ -5,15 +5,12 @@ static bool bad_usb_file_select(BadUsbApp* bad_usb) { furi_assert(bad_usb); + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options(&browser_options, BAD_USB_APP_EXTENSION, &I_badusb_10px); + // Input events and views are managed by file_browser bool res = dialog_file_browser_show( - bad_usb->dialogs, - bad_usb->file_path, - bad_usb->file_path, - BAD_USB_APP_EXTENSION, - true, - &I_badusb_10px, - true); + bad_usb->dialogs, bad_usb->file_path, bad_usb->file_path, &browser_options); return res; } diff --git a/applications/bad_usb/scenes/bad_usb_scene_work.c b/applications/main/bad_usb/scenes/bad_usb_scene_work.c similarity index 100% rename from applications/bad_usb/scenes/bad_usb_scene_work.c rename to applications/main/bad_usb/scenes/bad_usb_scene_work.c diff --git a/applications/bad_usb/views/bad_usb_view.c b/applications/main/bad_usb/views/bad_usb_view.c similarity index 100% rename from applications/bad_usb/views/bad_usb_view.c rename to applications/main/bad_usb/views/bad_usb_view.c diff --git a/applications/bad_usb/views/bad_usb_view.h b/applications/main/bad_usb/views/bad_usb_view.h similarity index 100% rename from applications/bad_usb/views/bad_usb_view.h rename to applications/main/bad_usb/views/bad_usb_view.h diff --git a/applications/main/fap_loader/application.fam b/applications/main/fap_loader/application.fam new file mode 100644 index 00000000..bd0403e0 --- /dev/null +++ b/applications/main/fap_loader/application.fam @@ -0,0 +1,13 @@ +App( + appid="fap_loader", + name="Applications", + apptype=FlipperAppType.APP, + entry_point="fap_loader_app", + requires=[ + "gui", + "storage", + ], + stack_size=int(1.5 * 1024), + icon="A_Plugins_14", + order=90, +) diff --git a/applications/main/fap_loader/elf_cpp/compilesort.hpp b/applications/main/fap_loader/elf_cpp/compilesort.hpp new file mode 100644 index 00000000..74661169 --- /dev/null +++ b/applications/main/fap_loader/elf_cpp/compilesort.hpp @@ -0,0 +1,111 @@ +/** + * Implementation of compile-time sort for symbol table entries. + */ + +#pragma once + +#include +#include + +namespace cstd { + +template +constexpr RAIt next(RAIt it, typename std::iterator_traits::difference_type n = 1) { + return it + n; +} + +template +constexpr auto distance(RAIt first, RAIt last) { + return last - first; +} + +template +constexpr void iter_swap(ForwardIt1 a, ForwardIt2 b) { + auto temp = std::move(*a); + *a = std::move(*b); + *b = std::move(temp); +} + +template +constexpr InputIt find_if_not(InputIt first, InputIt last, UnaryPredicate q) { + for(; first != last; ++first) { + if(!q(*first)) { + return first; + } + } + return last; +} + +template +constexpr ForwardIt partition(ForwardIt first, ForwardIt last, UnaryPredicate p) { + first = cstd::find_if_not(first, last, p); + if(first == last) return first; + + for(ForwardIt i = cstd::next(first); i != last; ++i) { + if(p(*i)) { + cstd::iter_swap(i, first); + ++first; + } + } + return first; +} + +} + +template > +constexpr void quick_sort(RAIt first, RAIt last, Compare cmp = Compare{}) { + auto const N = cstd::distance(first, last); + if(N <= 1) return; + auto const pivot = *cstd::next(first, N / 2); + auto const middle1 = + cstd::partition(first, last, [=](auto const& elem) { return cmp(elem, pivot); }); + auto const middle2 = + cstd::partition(middle1, last, [=](auto const& elem) { return !cmp(pivot, elem); }); + quick_sort(first, middle1, cmp); // assert(std::is_sorted(first, middle1, cmp)); + quick_sort(middle2, last, cmp); // assert(std::is_sorted(middle2, last, cmp)); +} + +template +constexpr auto sort(Range&& range) { + quick_sort(std::begin(range), std::end(range)); + return range; +} + +template +constexpr auto array_of(T&&... t) -> std::array { + return {{std::forward(t)...}}; +} + +template +constexpr auto my_make_array(N&&... args) -> std::array { + return {std::forward(args)...}; +} + +namespace traits { +template +struct array_type { + using type = T; +}; + +template +static constexpr bool are_same_type() { + return std::conjunction_v...>; +} + +} + +template +constexpr auto create_array(const T&&... values) { + using array_type = typename traits::array_type::type; + static_assert(sizeof...(T) > 0, "an array must have at least one element"); + static_assert(traits::are_same_type(), "all elements must have same type"); + return std::array{values...}; +} + +template +constexpr auto create_array_t(const Ts&&... values) { + using array_type = T; + static_assert(sizeof...(Ts) > 0, "an array must have at least one element"); + static_assert(traits::are_same_type(), "all elements must have same type"); + return std::array{static_cast(values)...}; +} diff --git a/applications/main/fap_loader/elf_cpp/elf_hashtable.cpp b/applications/main/fap_loader/elf_cpp/elf_hashtable.cpp new file mode 100644 index 00000000..17e2ba83 --- /dev/null +++ b/applications/main/fap_loader/elf_cpp/elf_hashtable.cpp @@ -0,0 +1,48 @@ +#include "compilesort.hpp" +#include "elf_hashtable.h" +#include "elf_hashtable_entry.h" +#include "elf_hashtable_checks.hpp" + +#include +#include + +/* Generated table */ +#include + +#define TAG "elf_hashtable" + +static_assert(!has_hash_collisions(elf_api_table), "Detected API method hash collision!"); + +/** + * Get function address by function name + * @param name function name + * @param address output for function address + * @return true if the table contains a function + */ + +bool elf_resolve_from_hashtable(const char* name, Elf32_Addr* address) { + bool result = false; + uint32_t gnu_sym_hash = elf_gnu_hash(name); + + sym_entry key = { + .hash = gnu_sym_hash, + .address = 0, + }; + + auto find_res = std::lower_bound(elf_api_table.cbegin(), elf_api_table.cend(), key); + if((find_res == elf_api_table.cend() || (find_res->hash != gnu_sym_hash))) { + FURI_LOG_W(TAG, "Cant find symbol '%s' (hash %x)!", name, gnu_sym_hash); + result = false; + } else { + result = true; + *address = find_res->address; + } + + return result; +} + +const ElfApiInterface hashtable_api_interface = { + .api_version_major = (elf_api_version >> 16), + .api_version_minor = (elf_api_version & 0xFFFF), + .resolver_callback = &elf_resolve_from_hashtable, +}; diff --git a/applications/main/fap_loader/elf_cpp/elf_hashtable.h b/applications/main/fap_loader/elf_cpp/elf_hashtable.h new file mode 100644 index 00000000..e574f116 --- /dev/null +++ b/applications/main/fap_loader/elf_cpp/elf_hashtable.h @@ -0,0 +1,14 @@ +#pragma once +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern const ElfApiInterface hashtable_api_interface; + +#ifdef __cplusplus +} +#endif diff --git a/applications/main/fap_loader/elf_cpp/elf_hashtable_checks.hpp b/applications/main/fap_loader/elf_cpp/elf_hashtable_checks.hpp new file mode 100644 index 00000000..61ee80e9 --- /dev/null +++ b/applications/main/fap_loader/elf_cpp/elf_hashtable_checks.hpp @@ -0,0 +1,18 @@ +/** + * Check for multiple entries with the same hash value at compilation time. + */ + +#pragma once +#include +#include "elf_hashtable_entry.h" + +template +constexpr bool has_hash_collisions(const std::array api_methods) { + for(std::size_t i = 0; i < (N - 1); ++i) { + if(api_methods[i].hash == api_methods[i + 1].hash) { + return true; + } + } + + return false; +} diff --git a/applications/main/fap_loader/elf_cpp/elf_hashtable_entry.h b/applications/main/fap_loader/elf_cpp/elf_hashtable_entry.h new file mode 100644 index 00000000..7b540fba --- /dev/null +++ b/applications/main/fap_loader/elf_cpp/elf_hashtable_entry.h @@ -0,0 +1,41 @@ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct sym_entry { + uint32_t hash; + uint32_t address; +}; + +#ifdef __cplusplus +} + +#include +#include + +#define API_METHOD(x, ret_type, args_type) \ + sym_entry { \ + .hash = elf_gnu_hash(#x), .address = (uint32_t)(static_cast(x)) \ + } + +#define API_VARIABLE(x, var_type) \ + sym_entry { \ + .hash = elf_gnu_hash(#x), .address = (uint32_t)(&(x)), \ + } + +constexpr bool operator<(const sym_entry& k1, const sym_entry& k2) { + return k1.hash < k2.hash; +} + +constexpr uint32_t elf_gnu_hash(const char* s) { + uint32_t h = 0x1505; + for(unsigned char c = *s; c != '\0'; c = *++s) { + h = (h << 5) + h + c; + } + return h; +} + +#endif diff --git a/applications/main/fap_loader/fap_loader_app.c b/applications/main/fap_loader/fap_loader_app.c new file mode 100644 index 00000000..14da2f32 --- /dev/null +++ b/applications/main/fap_loader/fap_loader_app.c @@ -0,0 +1,176 @@ +#include +#include +#include +#include +#include +#include +#include "elf_cpp/elf_hashtable.h" +#include + +#define TAG "fap_loader_app" + +typedef struct { + FlipperApplication* app; + Storage* storage; + DialogsApp* dialogs; + Gui* gui; + string_t fap_path; +} FapLoader; + +static bool + fap_loader_item_callback(string_t path, void* context, uint8_t** icon_ptr, string_t item_name) { + FapLoader* loader = context; + furi_assert(loader); + + FlipperApplication* app = flipper_application_alloc(loader->storage, &hashtable_api_interface); + + FlipperApplicationPreloadStatus preload_res = + flipper_application_preload(app, string_get_cstr(path)); + + bool load_success = false; + + if(preload_res == FlipperApplicationPreloadStatusSuccess) { + const FlipperApplicationManifest* manifest = flipper_application_get_manifest(app); + if(manifest->has_icon) { + memcpy(*icon_ptr, manifest->icon, FAP_MANIFEST_MAX_ICON_SIZE); + } + string_set_str(item_name, manifest->name); + load_success = true; + } else { + FURI_LOG_E(TAG, "FAP Loader failed to preload %s", string_get_cstr(path)); + load_success = false; + } + + flipper_application_free(app); + return load_success; +} + +static bool fap_loader_run_selected_app(FapLoader* loader) { + furi_assert(loader); + + string_t error_message; + + string_init_set(error_message, "unknown error"); + + bool file_selected = false; + bool show_error = true; + do { + file_selected = true; + loader->app = flipper_application_alloc(loader->storage, &hashtable_api_interface); + + FURI_LOG_I(TAG, "FAP Loader is loading %s", string_get_cstr(loader->fap_path)); + + FlipperApplicationPreloadStatus preload_res = + flipper_application_preload(loader->app, string_get_cstr(loader->fap_path)); + if(preload_res != FlipperApplicationPreloadStatusSuccess) { + const char* err_msg = flipper_application_preload_status_to_string(preload_res); + string_printf(error_message, "Preload failed: %s", err_msg); + FURI_LOG_E( + TAG, + "FAP Loader failed to preload %s: %s", + string_get_cstr(loader->fap_path), + err_msg); + break; + } + + FURI_LOG_I(TAG, "FAP Loader is mapping"); + FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(loader->app); + if(load_status != FlipperApplicationLoadStatusSuccess) { + const char* err_msg = flipper_application_load_status_to_string(load_status); + string_printf(error_message, "Load failed: %s", err_msg); + FURI_LOG_E( + TAG, + "FAP Loader failed to map to memory %s: %s", + string_get_cstr(loader->fap_path), + err_msg); + break; + } + + FURI_LOG_I(TAG, "FAP Loader is staring app"); + + FuriThread* thread = flipper_application_spawn(loader->app, NULL); + furi_thread_start(thread); + furi_thread_join(thread); + + show_error = false; + int ret = furi_thread_get_return_code(thread); + + FURI_LOG_I(TAG, "FAP app returned: %i", ret); + } while(0); + + if(show_error) { + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_header(message, "Error", 64, 0, AlignCenter, AlignTop); + dialog_message_set_buttons(message, NULL, NULL, NULL); + + string_t buffer; + string_init(buffer); + string_printf(buffer, "%s", string_get_cstr(error_message)); + string_replace_str(buffer, ":", "\n"); + dialog_message_set_text( + message, string_get_cstr(buffer), 64, 32, AlignCenter, AlignCenter); + + dialog_message_show(loader->dialogs, message); + dialog_message_free(message); + string_clear(buffer); + } + + string_clear(error_message); + + if(file_selected) { + flipper_application_free(loader->app); + } + + return file_selected; +} + +static bool fap_loader_select_app(FapLoader* loader) { + const DialogsFileBrowserOptions browser_options = { + .extension = ".fap", + .skip_assets = true, + .icon = &I_badusb_10px, + .hide_ext = true, + .item_loader_callback = fap_loader_item_callback, + .item_loader_context = loader, + }; + + return dialog_file_browser_show( + loader->dialogs, loader->fap_path, loader->fap_path, &browser_options); +} + +int32_t fap_loader_app(void* p) { + FapLoader* loader = malloc(sizeof(FapLoader)); + loader->storage = furi_record_open(RECORD_STORAGE); + loader->dialogs = furi_record_open(RECORD_DIALOGS); + loader->gui = furi_record_open(RECORD_GUI); + + ViewDispatcher* view_dispatcher = view_dispatcher_alloc(); + Loading* loading = loading_alloc(); + + view_dispatcher_enable_queue(view_dispatcher); + view_dispatcher_attach_to_gui(view_dispatcher, loader->gui, ViewDispatcherTypeFullscreen); + view_dispatcher_add_view(view_dispatcher, 0, loading_get_view(loading)); + + if(p) { + string_init_set(loader->fap_path, (const char*)p); + fap_loader_run_selected_app(loader); + } else { + string_init_set(loader->fap_path, EXT_PATH("apps")); + + while(fap_loader_select_app(loader)) { + view_dispatcher_switch_to_view(view_dispatcher, 0); + fap_loader_run_selected_app(loader); + }; + } + + view_dispatcher_remove_view(view_dispatcher, 0); + loading_free(loading); + view_dispatcher_free(view_dispatcher); + + string_clear(loader->fap_path); + furi_record_close(RECORD_GUI); + furi_record_close(RECORD_DIALOGS); + furi_record_close(RECORD_STORAGE); + free(loader); + return 0; +} \ No newline at end of file diff --git a/applications/gpio/application.fam b/applications/main/gpio/application.fam similarity index 100% rename from applications/gpio/application.fam rename to applications/main/gpio/application.fam diff --git a/applications/gpio/gpio_app.c b/applications/main/gpio/gpio_app.c similarity index 100% rename from applications/gpio/gpio_app.c rename to applications/main/gpio/gpio_app.c diff --git a/applications/gpio/gpio_app.h b/applications/main/gpio/gpio_app.h similarity index 100% rename from applications/gpio/gpio_app.h rename to applications/main/gpio/gpio_app.h diff --git a/applications/gpio/gpio_app_i.h b/applications/main/gpio/gpio_app_i.h similarity index 100% rename from applications/gpio/gpio_app_i.h rename to applications/main/gpio/gpio_app_i.h diff --git a/applications/gpio/gpio_custom_event.h b/applications/main/gpio/gpio_custom_event.h similarity index 100% rename from applications/gpio/gpio_custom_event.h rename to applications/main/gpio/gpio_custom_event.h diff --git a/applications/gpio/gpio_item.c b/applications/main/gpio/gpio_item.c similarity index 100% rename from applications/gpio/gpio_item.c rename to applications/main/gpio/gpio_item.c diff --git a/applications/gpio/gpio_item.h b/applications/main/gpio/gpio_item.h similarity index 100% rename from applications/gpio/gpio_item.h rename to applications/main/gpio/gpio_item.h diff --git a/applications/gpio/scenes/gpio_scene.c b/applications/main/gpio/scenes/gpio_scene.c similarity index 100% rename from applications/gpio/scenes/gpio_scene.c rename to applications/main/gpio/scenes/gpio_scene.c diff --git a/applications/gpio/scenes/gpio_scene.h b/applications/main/gpio/scenes/gpio_scene.h similarity index 100% rename from applications/gpio/scenes/gpio_scene.h rename to applications/main/gpio/scenes/gpio_scene.h diff --git a/applications/gpio/scenes/gpio_scene_config.h b/applications/main/gpio/scenes/gpio_scene_config.h similarity index 100% rename from applications/gpio/scenes/gpio_scene_config.h rename to applications/main/gpio/scenes/gpio_scene_config.h diff --git a/applications/gpio/scenes/gpio_scene_start.c b/applications/main/gpio/scenes/gpio_scene_start.c similarity index 100% rename from applications/gpio/scenes/gpio_scene_start.c rename to applications/main/gpio/scenes/gpio_scene_start.c diff --git a/applications/gpio/scenes/gpio_scene_test.c b/applications/main/gpio/scenes/gpio_scene_test.c similarity index 100% rename from applications/gpio/scenes/gpio_scene_test.c rename to applications/main/gpio/scenes/gpio_scene_test.c diff --git a/applications/gpio/scenes/gpio_scene_usb_uart.c b/applications/main/gpio/scenes/gpio_scene_usb_uart.c similarity index 100% rename from applications/gpio/scenes/gpio_scene_usb_uart.c rename to applications/main/gpio/scenes/gpio_scene_usb_uart.c diff --git a/applications/gpio/scenes/gpio_scene_usb_uart_close_rpc.c b/applications/main/gpio/scenes/gpio_scene_usb_uart_close_rpc.c similarity index 100% rename from applications/gpio/scenes/gpio_scene_usb_uart_close_rpc.c rename to applications/main/gpio/scenes/gpio_scene_usb_uart_close_rpc.c diff --git a/applications/gpio/scenes/gpio_scene_usb_uart_config.c b/applications/main/gpio/scenes/gpio_scene_usb_uart_config.c similarity index 100% rename from applications/gpio/scenes/gpio_scene_usb_uart_config.c rename to applications/main/gpio/scenes/gpio_scene_usb_uart_config.c diff --git a/applications/gpio/usb_uart_bridge.c b/applications/main/gpio/usb_uart_bridge.c similarity index 99% rename from applications/gpio/usb_uart_bridge.c rename to applications/main/gpio/usb_uart_bridge.c index 4623c4af..02f58ed1 100644 --- a/applications/gpio/usb_uart_bridge.c +++ b/applications/main/gpio/usb_uart_bridge.c @@ -1,7 +1,7 @@ #include "usb_uart_bridge.h" #include "furi_hal.h" #include -#include +#include #include "usb_cdc.h" #include "cli/cli_vcp.h" #include "cli/cli.h" diff --git a/applications/gpio/usb_uart_bridge.h b/applications/main/gpio/usb_uart_bridge.h similarity index 100% rename from applications/gpio/usb_uart_bridge.h rename to applications/main/gpio/usb_uart_bridge.h diff --git a/applications/gpio/views/gpio_test.c b/applications/main/gpio/views/gpio_test.c similarity index 100% rename from applications/gpio/views/gpio_test.c rename to applications/main/gpio/views/gpio_test.c diff --git a/applications/gpio/views/gpio_test.h b/applications/main/gpio/views/gpio_test.h similarity index 100% rename from applications/gpio/views/gpio_test.h rename to applications/main/gpio/views/gpio_test.h diff --git a/applications/gpio/views/gpio_usb_uart.c b/applications/main/gpio/views/gpio_usb_uart.c similarity index 100% rename from applications/gpio/views/gpio_usb_uart.c rename to applications/main/gpio/views/gpio_usb_uart.c diff --git a/applications/gpio/views/gpio_usb_uart.h b/applications/main/gpio/views/gpio_usb_uart.h similarity index 100% rename from applications/gpio/views/gpio_usb_uart.h rename to applications/main/gpio/views/gpio_usb_uart.h diff --git a/applications/ibutton/application.fam b/applications/main/ibutton/application.fam similarity index 100% rename from applications/ibutton/application.fam rename to applications/main/ibutton/application.fam diff --git a/applications/ibutton/ibutton.c b/applications/main/ibutton/ibutton.c similarity index 98% rename from applications/ibutton/ibutton.c rename to applications/main/ibutton/ibutton.c index 7ee1110e..e9ec614e 100644 --- a/applications/ibutton/ibutton.c +++ b/applications/main/ibutton/ibutton.c @@ -216,14 +216,11 @@ void ibutton_free(iButton* ibutton) { } bool ibutton_file_select(iButton* ibutton) { + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options(&browser_options, IBUTTON_APP_EXTENSION, &I_ibutt_10px); + bool success = dialog_file_browser_show( - ibutton->dialogs, - ibutton->file_path, - ibutton->file_path, - IBUTTON_APP_EXTENSION, - true, - &I_ibutt_10px, - true); + ibutton->dialogs, ibutton->file_path, ibutton->file_path, &browser_options); if(success) { success = ibutton_load_key_data(ibutton, ibutton->file_path, true); diff --git a/applications/ibutton/ibutton.h b/applications/main/ibutton/ibutton.h similarity index 100% rename from applications/ibutton/ibutton.h rename to applications/main/ibutton/ibutton.h diff --git a/applications/ibutton/ibutton_cli.c b/applications/main/ibutton/ibutton_cli.c similarity index 100% rename from applications/ibutton/ibutton_cli.c rename to applications/main/ibutton/ibutton_cli.c diff --git a/applications/ibutton/ibutton_custom_event.h b/applications/main/ibutton/ibutton_custom_event.h similarity index 100% rename from applications/ibutton/ibutton_custom_event.h rename to applications/main/ibutton/ibutton_custom_event.h diff --git a/applications/ibutton/ibutton_i.h b/applications/main/ibutton/ibutton_i.h similarity index 100% rename from applications/ibutton/ibutton_i.h rename to applications/main/ibutton/ibutton_i.h diff --git a/applications/ibutton/scenes/ibutton_scene.c b/applications/main/ibutton/scenes/ibutton_scene.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene.c rename to applications/main/ibutton/scenes/ibutton_scene.c diff --git a/applications/ibutton/scenes/ibutton_scene.h b/applications/main/ibutton/scenes/ibutton_scene.h similarity index 100% rename from applications/ibutton/scenes/ibutton_scene.h rename to applications/main/ibutton/scenes/ibutton_scene.h diff --git a/applications/ibutton/scenes/ibutton_scene_add_type.c b/applications/main/ibutton/scenes/ibutton_scene_add_type.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_add_type.c rename to applications/main/ibutton/scenes/ibutton_scene_add_type.c diff --git a/applications/ibutton/scenes/ibutton_scene_add_value.c b/applications/main/ibutton/scenes/ibutton_scene_add_value.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_add_value.c rename to applications/main/ibutton/scenes/ibutton_scene_add_value.c diff --git a/applications/ibutton/scenes/ibutton_scene_config.h b/applications/main/ibutton/scenes/ibutton_scene_config.h similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_config.h rename to applications/main/ibutton/scenes/ibutton_scene_config.h diff --git a/applications/ibutton/scenes/ibutton_scene_delete_confirm.c b/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_delete_confirm.c rename to applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c diff --git a/applications/ibutton/scenes/ibutton_scene_delete_success.c b/applications/main/ibutton/scenes/ibutton_scene_delete_success.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_delete_success.c rename to applications/main/ibutton/scenes/ibutton_scene_delete_success.c diff --git a/applications/ibutton/scenes/ibutton_scene_emulate.c b/applications/main/ibutton/scenes/ibutton_scene_emulate.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_emulate.c rename to applications/main/ibutton/scenes/ibutton_scene_emulate.c diff --git a/applications/ibutton/scenes/ibutton_scene_exit_confirm.c b/applications/main/ibutton/scenes/ibutton_scene_exit_confirm.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_exit_confirm.c rename to applications/main/ibutton/scenes/ibutton_scene_exit_confirm.c diff --git a/applications/ibutton/scenes/ibutton_scene_info.c b/applications/main/ibutton/scenes/ibutton_scene_info.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_info.c rename to applications/main/ibutton/scenes/ibutton_scene_info.c diff --git a/applications/ibutton/scenes/ibutton_scene_read.c b/applications/main/ibutton/scenes/ibutton_scene_read.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_read.c rename to applications/main/ibutton/scenes/ibutton_scene_read.c diff --git a/applications/ibutton/scenes/ibutton_scene_read_crc_error.c b/applications/main/ibutton/scenes/ibutton_scene_read_crc_error.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_read_crc_error.c rename to applications/main/ibutton/scenes/ibutton_scene_read_crc_error.c diff --git a/applications/ibutton/scenes/ibutton_scene_read_key_menu.c b/applications/main/ibutton/scenes/ibutton_scene_read_key_menu.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_read_key_menu.c rename to applications/main/ibutton/scenes/ibutton_scene_read_key_menu.c diff --git a/applications/ibutton/scenes/ibutton_scene_read_not_key_error.c b/applications/main/ibutton/scenes/ibutton_scene_read_not_key_error.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_read_not_key_error.c rename to applications/main/ibutton/scenes/ibutton_scene_read_not_key_error.c diff --git a/applications/ibutton/scenes/ibutton_scene_read_success.c b/applications/main/ibutton/scenes/ibutton_scene_read_success.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_read_success.c rename to applications/main/ibutton/scenes/ibutton_scene_read_success.c diff --git a/applications/ibutton/scenes/ibutton_scene_retry_confirm.c b/applications/main/ibutton/scenes/ibutton_scene_retry_confirm.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_retry_confirm.c rename to applications/main/ibutton/scenes/ibutton_scene_retry_confirm.c diff --git a/applications/ibutton/scenes/ibutton_scene_rpc.c b/applications/main/ibutton/scenes/ibutton_scene_rpc.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_rpc.c rename to applications/main/ibutton/scenes/ibutton_scene_rpc.c diff --git a/applications/ibutton/scenes/ibutton_scene_save_name.c b/applications/main/ibutton/scenes/ibutton_scene_save_name.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_save_name.c rename to applications/main/ibutton/scenes/ibutton_scene_save_name.c diff --git a/applications/ibutton/scenes/ibutton_scene_save_success.c b/applications/main/ibutton/scenes/ibutton_scene_save_success.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_save_success.c rename to applications/main/ibutton/scenes/ibutton_scene_save_success.c diff --git a/applications/ibutton/scenes/ibutton_scene_saved_key_menu.c b/applications/main/ibutton/scenes/ibutton_scene_saved_key_menu.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_saved_key_menu.c rename to applications/main/ibutton/scenes/ibutton_scene_saved_key_menu.c diff --git a/applications/ibutton/scenes/ibutton_scene_select_key.c b/applications/main/ibutton/scenes/ibutton_scene_select_key.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_select_key.c rename to applications/main/ibutton/scenes/ibutton_scene_select_key.c diff --git a/applications/ibutton/scenes/ibutton_scene_start.c b/applications/main/ibutton/scenes/ibutton_scene_start.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_start.c rename to applications/main/ibutton/scenes/ibutton_scene_start.c diff --git a/applications/ibutton/scenes/ibutton_scene_write.c b/applications/main/ibutton/scenes/ibutton_scene_write.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_write.c rename to applications/main/ibutton/scenes/ibutton_scene_write.c diff --git a/applications/ibutton/scenes/ibutton_scene_write_success.c b/applications/main/ibutton/scenes/ibutton_scene_write_success.c similarity index 100% rename from applications/ibutton/scenes/ibutton_scene_write_success.c rename to applications/main/ibutton/scenes/ibutton_scene_write_success.c diff --git a/applications/infrared/application.fam b/applications/main/infrared/application.fam similarity index 100% rename from applications/infrared/application.fam rename to applications/main/infrared/application.fam diff --git a/applications/infrared/infrared.c b/applications/main/infrared/infrared.c similarity index 100% rename from applications/infrared/infrared.c rename to applications/main/infrared/infrared.c diff --git a/applications/infrared/infrared.h b/applications/main/infrared/infrared.h similarity index 100% rename from applications/infrared/infrared.h rename to applications/main/infrared/infrared.h diff --git a/applications/infrared/infrared_brute_force.c b/applications/main/infrared/infrared_brute_force.c similarity index 97% rename from applications/infrared/infrared_brute_force.c rename to applications/main/infrared/infrared_brute_force.c index 8dbc2301..575fa05e 100644 --- a/applications/infrared/infrared_brute_force.c +++ b/applications/main/infrared/infrared_brute_force.c @@ -153,3 +153,7 @@ void infrared_brute_force_add_record( InfraredBruteForceRecordDict_set_at(brute_force->records, key, value); string_clear(key); } + +void infrared_brute_force_reset(InfraredBruteForce* brute_force) { + InfraredBruteForceRecordDict_reset(brute_force->records); +} diff --git a/applications/infrared/infrared_brute_force.h b/applications/main/infrared/infrared_brute_force.h similarity index 92% rename from applications/infrared/infrared_brute_force.h rename to applications/main/infrared/infrared_brute_force.h index acf0d7b6..042d1556 100644 --- a/applications/infrared/infrared_brute_force.h +++ b/applications/main/infrared/infrared_brute_force.h @@ -20,3 +20,4 @@ void infrared_brute_force_add_record( InfraredBruteForce* brute_force, uint32_t index, const char* name); +void infrared_brute_force_reset(InfraredBruteForce* brute_force); diff --git a/applications/infrared/infrared_cli.c b/applications/main/infrared/infrared_cli.c similarity index 100% rename from applications/infrared/infrared_cli.c rename to applications/main/infrared/infrared_cli.c diff --git a/applications/infrared/infrared_custom_event.h b/applications/main/infrared/infrared_custom_event.h similarity index 100% rename from applications/infrared/infrared_custom_event.h rename to applications/main/infrared/infrared_custom_event.h diff --git a/applications/infrared/infrared_i.h b/applications/main/infrared/infrared_i.h similarity index 100% rename from applications/infrared/infrared_i.h rename to applications/main/infrared/infrared_i.h diff --git a/applications/infrared/infrared_remote.c b/applications/main/infrared/infrared_remote.c similarity index 100% rename from applications/infrared/infrared_remote.c rename to applications/main/infrared/infrared_remote.c diff --git a/applications/infrared/infrared_remote.h b/applications/main/infrared/infrared_remote.h similarity index 100% rename from applications/infrared/infrared_remote.h rename to applications/main/infrared/infrared_remote.h diff --git a/applications/infrared/infrared_remote_button.c b/applications/main/infrared/infrared_remote_button.c similarity index 100% rename from applications/infrared/infrared_remote_button.c rename to applications/main/infrared/infrared_remote_button.c diff --git a/applications/infrared/infrared_remote_button.h b/applications/main/infrared/infrared_remote_button.h similarity index 100% rename from applications/infrared/infrared_remote_button.h rename to applications/main/infrared/infrared_remote_button.h diff --git a/applications/infrared/infrared_signal.c b/applications/main/infrared/infrared_signal.c similarity index 100% rename from applications/infrared/infrared_signal.c rename to applications/main/infrared/infrared_signal.c diff --git a/applications/infrared/infrared_signal.h b/applications/main/infrared/infrared_signal.h similarity index 100% rename from applications/infrared/infrared_signal.h rename to applications/main/infrared/infrared_signal.h diff --git a/applications/infrared/scenes/common/infrared_scene_universal_common.c b/applications/main/infrared/scenes/common/infrared_scene_universal_common.c similarity index 98% rename from applications/infrared/scenes/common/infrared_scene_universal_common.c rename to applications/main/infrared/scenes/common/infrared_scene_universal_common.c index 57ac8116..f823ca93 100644 --- a/applications/infrared/scenes/common/infrared_scene_universal_common.c +++ b/applications/main/infrared/scenes/common/infrared_scene_universal_common.c @@ -87,5 +87,6 @@ void infrared_scene_universal_common_on_exit(void* context) { Infrared* infrared = context; ButtonPanel* button_panel = infrared->button_panel; view_stack_remove_view(infrared->view_stack, button_panel_get_view(button_panel)); + infrared_brute_force_reset(infrared->brute_force); button_panel_reset(button_panel); } diff --git a/applications/infrared/scenes/common/infrared_scene_universal_common.h b/applications/main/infrared/scenes/common/infrared_scene_universal_common.h similarity index 100% rename from applications/infrared/scenes/common/infrared_scene_universal_common.h rename to applications/main/infrared/scenes/common/infrared_scene_universal_common.h diff --git a/applications/infrared/scenes/infrared_scene.c b/applications/main/infrared/scenes/infrared_scene.c similarity index 100% rename from applications/infrared/scenes/infrared_scene.c rename to applications/main/infrared/scenes/infrared_scene.c diff --git a/applications/infrared/scenes/infrared_scene.h b/applications/main/infrared/scenes/infrared_scene.h similarity index 100% rename from applications/infrared/scenes/infrared_scene.h rename to applications/main/infrared/scenes/infrared_scene.h diff --git a/applications/infrared/scenes/infrared_scene_ask_back.c b/applications/main/infrared/scenes/infrared_scene_ask_back.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_ask_back.c rename to applications/main/infrared/scenes/infrared_scene_ask_back.c diff --git a/applications/infrared/scenes/infrared_scene_ask_retry.c b/applications/main/infrared/scenes/infrared_scene_ask_retry.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_ask_retry.c rename to applications/main/infrared/scenes/infrared_scene_ask_retry.c diff --git a/applications/infrared/scenes/infrared_scene_config.h b/applications/main/infrared/scenes/infrared_scene_config.h similarity index 94% rename from applications/infrared/scenes/infrared_scene_config.h rename to applications/main/infrared/scenes/infrared_scene_config.h index 26a92056..22125fb7 100644 --- a/applications/infrared/scenes/infrared_scene_config.h +++ b/applications/main/infrared/scenes/infrared_scene_config.h @@ -15,6 +15,7 @@ ADD_SCENE(infrared, remote, Remote) ADD_SCENE(infrared, remote_list, RemoteList) ADD_SCENE(infrared, universal, Universal) ADD_SCENE(infrared, universal_tv, UniversalTV) +ADD_SCENE(infrared, universal_ac, UniversalAC) ADD_SCENE(infrared, debug, Debug) ADD_SCENE(infrared, error_databases, ErrorDatabases) ADD_SCENE(infrared, rpc, Rpc) diff --git a/applications/infrared/scenes/infrared_scene_debug.c b/applications/main/infrared/scenes/infrared_scene_debug.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_debug.c rename to applications/main/infrared/scenes/infrared_scene_debug.c diff --git a/applications/infrared/scenes/infrared_scene_edit.c b/applications/main/infrared/scenes/infrared_scene_edit.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_edit.c rename to applications/main/infrared/scenes/infrared_scene_edit.c diff --git a/applications/infrared/scenes/infrared_scene_edit_button_select.c b/applications/main/infrared/scenes/infrared_scene_edit_button_select.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_edit_button_select.c rename to applications/main/infrared/scenes/infrared_scene_edit_button_select.c diff --git a/applications/infrared/scenes/infrared_scene_edit_delete.c b/applications/main/infrared/scenes/infrared_scene_edit_delete.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_edit_delete.c rename to applications/main/infrared/scenes/infrared_scene_edit_delete.c diff --git a/applications/infrared/scenes/infrared_scene_edit_delete_done.c b/applications/main/infrared/scenes/infrared_scene_edit_delete_done.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_edit_delete_done.c rename to applications/main/infrared/scenes/infrared_scene_edit_delete_done.c diff --git a/applications/infrared/scenes/infrared_scene_edit_rename.c b/applications/main/infrared/scenes/infrared_scene_edit_rename.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_edit_rename.c rename to applications/main/infrared/scenes/infrared_scene_edit_rename.c diff --git a/applications/infrared/scenes/infrared_scene_edit_rename_done.c b/applications/main/infrared/scenes/infrared_scene_edit_rename_done.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_edit_rename_done.c rename to applications/main/infrared/scenes/infrared_scene_edit_rename_done.c diff --git a/applications/infrared/scenes/infrared_scene_error_databases.c b/applications/main/infrared/scenes/infrared_scene_error_databases.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_error_databases.c rename to applications/main/infrared/scenes/infrared_scene_error_databases.c diff --git a/applications/infrared/scenes/infrared_scene_learn.c b/applications/main/infrared/scenes/infrared_scene_learn.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_learn.c rename to applications/main/infrared/scenes/infrared_scene_learn.c diff --git a/applications/infrared/scenes/infrared_scene_learn_done.c b/applications/main/infrared/scenes/infrared_scene_learn_done.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_learn_done.c rename to applications/main/infrared/scenes/infrared_scene_learn_done.c diff --git a/applications/infrared/scenes/infrared_scene_learn_enter_name.c b/applications/main/infrared/scenes/infrared_scene_learn_enter_name.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_learn_enter_name.c rename to applications/main/infrared/scenes/infrared_scene_learn_enter_name.c diff --git a/applications/infrared/scenes/infrared_scene_learn_success.c b/applications/main/infrared/scenes/infrared_scene_learn_success.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_learn_success.c rename to applications/main/infrared/scenes/infrared_scene_learn_success.c diff --git a/applications/infrared/scenes/infrared_scene_remote.c b/applications/main/infrared/scenes/infrared_scene_remote.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_remote.c rename to applications/main/infrared/scenes/infrared_scene_remote.c diff --git a/applications/infrared/scenes/infrared_scene_remote_list.c b/applications/main/infrared/scenes/infrared_scene_remote_list.c similarity index 82% rename from applications/infrared/scenes/infrared_scene_remote_list.c rename to applications/main/infrared/scenes/infrared_scene_remote_list.c index b0038c1a..1667352d 100644 --- a/applications/infrared/scenes/infrared_scene_remote_list.c +++ b/applications/main/infrared/scenes/infrared_scene_remote_list.c @@ -5,14 +5,11 @@ void infrared_scene_remote_list_on_enter(void* context) { SceneManager* scene_manager = infrared->scene_manager; ViewDispatcher* view_dispatcher = infrared->view_dispatcher; + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options(&browser_options, INFRARED_APP_EXTENSION, &I_ir_10px); + bool success = dialog_file_browser_show( - infrared->dialogs, - infrared->file_path, - infrared->file_path, - INFRARED_APP_EXTENSION, - true, - &I_ir_10px, - true); + infrared->dialogs, infrared->file_path, infrared->file_path, &browser_options); if(success) { view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); diff --git a/applications/infrared/scenes/infrared_scene_rpc.c b/applications/main/infrared/scenes/infrared_scene_rpc.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_rpc.c rename to applications/main/infrared/scenes/infrared_scene_rpc.c diff --git a/applications/infrared/scenes/infrared_scene_start.c b/applications/main/infrared/scenes/infrared_scene_start.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_start.c rename to applications/main/infrared/scenes/infrared_scene_start.c diff --git a/applications/infrared/scenes/infrared_scene_universal.c b/applications/main/infrared/scenes/infrared_scene_universal.c similarity index 81% rename from applications/infrared/scenes/infrared_scene_universal.c rename to applications/main/infrared/scenes/infrared_scene_universal.c index cc656883..2bd7082c 100644 --- a/applications/infrared/scenes/infrared_scene_universal.c +++ b/applications/main/infrared/scenes/infrared_scene_universal.c @@ -2,8 +2,8 @@ typedef enum { SubmenuIndexUniversalTV, + SubmenuIndexUniversalAC, SubmenuIndexUniversalAudio, - SubmenuIndexUniversalAirConditioner, } SubmenuIndex; static void infrared_scene_universal_submenu_callback(void* context, uint32_t index) { @@ -21,6 +21,12 @@ void infrared_scene_universal_on_enter(void* context) { SubmenuIndexUniversalTV, infrared_scene_universal_submenu_callback, context); + submenu_add_item( + submenu, + "Air Conditioners", + SubmenuIndexUniversalAC, + infrared_scene_universal_submenu_callback, + context); submenu_set_selected_item(submenu, 0); view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewSubmenu); @@ -35,12 +41,12 @@ bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) { if(event.event == SubmenuIndexUniversalTV) { scene_manager_next_scene(scene_manager, InfraredSceneUniversalTV); consumed = true; + } else if(event.event == SubmenuIndexUniversalAC) { + scene_manager_next_scene(scene_manager, InfraredSceneUniversalAC); + consumed = true; } else if(event.event == SubmenuIndexUniversalAudio) { //TODO Implement Audio universal remote consumed = true; - } else if(event.event == SubmenuIndexUniversalAirConditioner) { - //TODO Implement A/C universal remote - consumed = true; } } diff --git a/applications/main/infrared/scenes/infrared_scene_universal_ac.c b/applications/main/infrared/scenes/infrared_scene_universal_ac.c new file mode 100644 index 00000000..58f06773 --- /dev/null +++ b/applications/main/infrared/scenes/infrared_scene_universal_ac.c @@ -0,0 +1,109 @@ +#include "../infrared_i.h" + +#include "common/infrared_scene_universal_common.h" + +void infrared_scene_universal_ac_on_enter(void* context) { + infrared_scene_universal_common_on_enter(context); + + Infrared* infrared = context; + ButtonPanel* button_panel = infrared->button_panel; + InfraredBruteForce* brute_force = infrared->brute_force; + + infrared_brute_force_set_db_filename(brute_force, EXT_PATH("infrared/assets/ac.ir")); + + button_panel_reserve(button_panel, 2, 3); + uint32_t i = 0; + button_panel_add_item( + button_panel, + i, + 0, + 0, + 3, + 22, + &I_Off_25x27, + &I_Off_hvr_25x27, + infrared_scene_universal_common_item_callback, + context); + infrared_brute_force_add_record(brute_force, i++, "Off"); + button_panel_add_item( + button_panel, + i, + 1, + 0, + 36, + 22, + &I_Dehumidify_25x27, + &I_Dehumidify_hvr_25x27, + infrared_scene_universal_common_item_callback, + context); + infrared_brute_force_add_record(brute_force, i++, "Dh"); + button_panel_add_item( + button_panel, + i, + 0, + 1, + 3, + 59, + &I_CoolHi_25x27, + &I_CoolHi_hvr_25x27, + infrared_scene_universal_common_item_callback, + context); + infrared_brute_force_add_record(brute_force, i++, "Cool_hi"); + button_panel_add_item( + button_panel, + i, + 1, + 1, + 36, + 59, + &I_HeatHi_25x27, + &I_HeatHi_hvr_25x27, + infrared_scene_universal_common_item_callback, + context); + infrared_brute_force_add_record(brute_force, i++, "Heat_hi"); + button_panel_add_item( + button_panel, + i, + 0, + 2, + 3, + 91, + &I_CoolLo_25x27, + &I_CoolLo_hvr_25x27, + infrared_scene_universal_common_item_callback, + context); + infrared_brute_force_add_record(brute_force, i++, "Cool_lo"); + button_panel_add_item( + button_panel, + i, + 1, + 2, + 36, + 91, + &I_HeatLo_25x27, + &I_HeatLo_hvr_25x27, + infrared_scene_universal_common_item_callback, + context); + infrared_brute_force_add_record(brute_force, i++, "Heat_lo"); + + button_panel_add_label(button_panel, 6, 10, FontPrimary, "AC remote"); + + view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); + + infrared_show_loading_popup(infrared, true); + bool success = infrared_brute_force_calculate_messages(brute_force); + infrared_show_loading_popup(infrared, false); + + if(!success) { + scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases); + } +} + +bool infrared_scene_universal_ac_on_event(void* context, SceneManagerEvent event) { + return infrared_scene_universal_common_on_event(context, event); +} + +void infrared_scene_universal_ac_on_exit(void* context) { + infrared_scene_universal_common_on_exit(context); +} diff --git a/applications/infrared/scenes/infrared_scene_universal_tv.c b/applications/main/infrared/scenes/infrared_scene_universal_tv.c similarity index 100% rename from applications/infrared/scenes/infrared_scene_universal_tv.c rename to applications/main/infrared/scenes/infrared_scene_universal_tv.c diff --git a/applications/infrared/views/infrared_debug_view.c b/applications/main/infrared/views/infrared_debug_view.c similarity index 100% rename from applications/infrared/views/infrared_debug_view.c rename to applications/main/infrared/views/infrared_debug_view.c diff --git a/applications/infrared/views/infrared_debug_view.h b/applications/main/infrared/views/infrared_debug_view.h similarity index 100% rename from applications/infrared/views/infrared_debug_view.h rename to applications/main/infrared/views/infrared_debug_view.h diff --git a/applications/infrared/views/infrared_progress_view.c b/applications/main/infrared/views/infrared_progress_view.c similarity index 100% rename from applications/infrared/views/infrared_progress_view.c rename to applications/main/infrared/views/infrared_progress_view.c diff --git a/applications/infrared/views/infrared_progress_view.h b/applications/main/infrared/views/infrared_progress_view.h similarity index 100% rename from applications/infrared/views/infrared_progress_view.h rename to applications/main/infrared/views/infrared_progress_view.h diff --git a/applications/lfrfid/application.fam b/applications/main/lfrfid/application.fam similarity index 95% rename from applications/lfrfid/application.fam rename to applications/main/lfrfid/application.fam index 8722bb4f..4a149818 100644 --- a/applications/lfrfid/application.fam +++ b/applications/main/lfrfid/application.fam @@ -10,7 +10,6 @@ App( ], provides=[ "lfrfid_start", - "lfrfid_debug", ], icon="A_125khz_14", stack_size=2 * 1024, diff --git a/applications/main/lfrfid/lfrfid.c b/applications/main/lfrfid/lfrfid.c new file mode 100644 index 00000000..dbed9f3a --- /dev/null +++ b/applications/main/lfrfid/lfrfid.c @@ -0,0 +1,314 @@ +#include "lfrfid_i.h" + +static bool lfrfid_debug_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + LfRfid* app = context; + return scene_manager_handle_custom_event(app->scene_manager, event); +} + +static bool lfrfid_debug_back_event_callback(void* context) { + furi_assert(context); + LfRfid* app = context; + return scene_manager_handle_back_event(app->scene_manager); +} + +static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) { + furi_assert(context); + LfRfid* app = (LfRfid*)context; + + if(rpc_event == RpcAppEventSessionClose) { + view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventRpcSessionClose); + // Detach RPC + rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL); + app->rpc_ctx = NULL; + } else if(rpc_event == RpcAppEventAppExit) { + view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventExit); + } else if(rpc_event == RpcAppEventLoadFile) { + view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventRpcLoadFile); + } else { + rpc_system_app_confirm(app->rpc_ctx, rpc_event, false); + } +} + +static LfRfid* lfrfid_alloc() { + LfRfid* lfrfid = malloc(sizeof(LfRfid)); + + lfrfid->storage = furi_record_open(RECORD_STORAGE); + lfrfid->dialogs = furi_record_open(RECORD_DIALOGS); + + string_init(lfrfid->file_name); + string_init(lfrfid->raw_file_name); + string_init_set_str(lfrfid->file_path, LFRFID_APP_FOLDER); + + lfrfid->dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax); + + size_t size = protocol_dict_get_max_data_size(lfrfid->dict); + lfrfid->new_key_data = (uint8_t*)malloc(size); + lfrfid->old_key_data = (uint8_t*)malloc(size); + + lfrfid->lfworker = lfrfid_worker_alloc(lfrfid->dict); + + lfrfid->view_dispatcher = view_dispatcher_alloc(); + lfrfid->scene_manager = scene_manager_alloc(&lfrfid_scene_handlers, lfrfid); + view_dispatcher_enable_queue(lfrfid->view_dispatcher); + view_dispatcher_set_event_callback_context(lfrfid->view_dispatcher, lfrfid); + view_dispatcher_set_custom_event_callback( + lfrfid->view_dispatcher, lfrfid_debug_custom_event_callback); + view_dispatcher_set_navigation_event_callback( + lfrfid->view_dispatcher, lfrfid_debug_back_event_callback); + + // Open GUI record + lfrfid->gui = furi_record_open(RECORD_GUI); + + // Open Notification record + lfrfid->notifications = furi_record_open(RECORD_NOTIFICATION); + + // Submenu + lfrfid->submenu = submenu_alloc(); + view_dispatcher_add_view( + lfrfid->view_dispatcher, LfRfidViewSubmenu, submenu_get_view(lfrfid->submenu)); + + // Dialog + lfrfid->dialog_ex = dialog_ex_alloc(); + view_dispatcher_add_view( + lfrfid->view_dispatcher, LfRfidViewDialogEx, dialog_ex_get_view(lfrfid->dialog_ex)); + + // Popup + lfrfid->popup = popup_alloc(); + view_dispatcher_add_view( + lfrfid->view_dispatcher, LfRfidViewPopup, popup_get_view(lfrfid->popup)); + + // Widget + lfrfid->widget = widget_alloc(); + view_dispatcher_add_view( + lfrfid->view_dispatcher, LfRfidViewWidget, widget_get_view(lfrfid->widget)); + + // Text Input + lfrfid->text_input = text_input_alloc(); + view_dispatcher_add_view( + lfrfid->view_dispatcher, LfRfidViewTextInput, text_input_get_view(lfrfid->text_input)); + + // Byte Input + lfrfid->byte_input = byte_input_alloc(); + view_dispatcher_add_view( + lfrfid->view_dispatcher, LfRfidViewByteInput, byte_input_get_view(lfrfid->byte_input)); + + // Read custom view + lfrfid->read_view = lfrfid_view_read_alloc(); + view_dispatcher_add_view( + lfrfid->view_dispatcher, LfRfidViewRead, lfrfid_view_read_get_view(lfrfid->read_view)); + + return lfrfid; +} + +static void lfrfid_free(LfRfid* lfrfid) { + furi_assert(lfrfid); + + string_clear(lfrfid->raw_file_name); + string_clear(lfrfid->file_name); + string_clear(lfrfid->file_path); + protocol_dict_free(lfrfid->dict); + + lfrfid_worker_free(lfrfid->lfworker); + + if(lfrfid->rpc_ctx) { + rpc_system_app_set_callback(lfrfid->rpc_ctx, NULL, NULL); + rpc_system_app_send_exited(lfrfid->rpc_ctx); + } + + free(lfrfid->new_key_data); + free(lfrfid->old_key_data); + + // Submenu + view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewSubmenu); + submenu_free(lfrfid->submenu); + + // DialogEx + view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewDialogEx); + dialog_ex_free(lfrfid->dialog_ex); + + // Popup + view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewPopup); + popup_free(lfrfid->popup); + + // Widget + view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewWidget); + widget_free(lfrfid->widget); + + // TextInput + view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewTextInput); + text_input_free(lfrfid->text_input); + + // ByteInput + view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewByteInput); + byte_input_free(lfrfid->byte_input); + + // Read custom view + view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewRead); + lfrfid_view_read_free(lfrfid->read_view); + + // View Dispatcher + view_dispatcher_free(lfrfid->view_dispatcher); + + // Scene Manager + scene_manager_free(lfrfid->scene_manager); + + // GUI + furi_record_close(RECORD_GUI); + lfrfid->gui = NULL; + + // Notifications + furi_record_close(RECORD_NOTIFICATION); + lfrfid->notifications = NULL; + + furi_record_close(RECORD_STORAGE); + furi_record_close(RECORD_DIALOGS); + + free(lfrfid); +} + +int32_t lfrfid_app(void* p) { + LfRfid* app = lfrfid_alloc(); + char* args = p; + + lfrfid_make_app_folder(app); + + if(args && strlen(args)) { + uint32_t rpc_ctx_ptr = 0; + if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) { + app->rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr; + rpc_system_app_set_callback(app->rpc_ctx, rpc_command_callback, app); + rpc_system_app_send_started(app->rpc_ctx); + view_dispatcher_attach_to_gui( + app->view_dispatcher, app->gui, ViewDispatcherTypeDesktop); + scene_manager_next_scene(app->scene_manager, LfRfidSceneRpc); + } else { + string_set_str(app->file_path, args); + lfrfid_load_key_data(app, app->file_path, true); + view_dispatcher_attach_to_gui( + app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate); + } + + } else { + view_dispatcher_attach_to_gui( + app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + scene_manager_next_scene(app->scene_manager, LfRfidSceneStart); + } + + view_dispatcher_run(app->view_dispatcher); + + lfrfid_free(app); + + return 0; +} + +bool lfrfid_save_key(LfRfid* app) { + furi_assert(app); + + bool result = false; + + lfrfid_make_app_folder(app); + + if(string_end_with_str_p(app->file_path, LFRFID_APP_EXTENSION)) { + size_t filename_start = string_search_rchar(app->file_path, '/'); + string_left(app->file_path, filename_start); + } + + string_cat_printf( + app->file_path, "/%s%s", string_get_cstr(app->file_name), LFRFID_APP_EXTENSION); + + result = lfrfid_save_key_data(app, app->file_path); + return result; +} + +bool lfrfid_load_key_from_file_select(LfRfid* app) { + furi_assert(app); + + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options(&browser_options, LFRFID_APP_EXTENSION, &I_125_10px); + + // Input events and views are managed by file_browser + bool result = + dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options); + + if(result) { + result = lfrfid_load_key_data(app, app->file_path, true); + } + + return result; +} + +bool lfrfid_delete_key(LfRfid* app) { + furi_assert(app); + + return storage_simply_remove(app->storage, string_get_cstr(app->file_path)); +} + +bool lfrfid_load_key_data(LfRfid* app, string_t path, bool show_dialog) { + bool result = false; + + do { + app->protocol_id = lfrfid_dict_file_load(app->dict, string_get_cstr(path)); + if(app->protocol_id == PROTOCOL_NO) break; + + path_extract_filename(path, app->file_name, true); + result = true; + } while(0); + + if((!result) && (show_dialog)) { + dialog_message_show_storage_error(app->dialogs, "Cannot load\nkey file"); + } + + return result; +} + +bool lfrfid_save_key_data(LfRfid* app, string_t path) { + bool result = lfrfid_dict_file_save(app->dict, app->protocol_id, string_get_cstr(path)); + + if(!result) { + dialog_message_show_storage_error(app->dialogs, "Cannot save\nkey file"); + } + + return result; +} + +void lfrfid_make_app_folder(LfRfid* app) { + furi_assert(app); + + if(!storage_simply_mkdir(app->storage, LFRFID_APP_FOLDER)) { + dialog_message_show_storage_error(app->dialogs, "Cannot create\napp folder"); + } +} + +void lfrfid_text_store_set(LfRfid* app, const char* text, ...) { + furi_assert(app); + va_list args; + va_start(args, text); + + vsnprintf(app->text_store, LFRFID_TEXT_STORE_SIZE, text, args); + + va_end(args); +} + +void lfrfid_text_store_clear(LfRfid* app) { + furi_assert(app); + memset(app->text_store, 0, sizeof(app->text_store)); +} + +void lfrfid_popup_timeout_callback(void* context) { + LfRfid* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventPopupClosed); +} + +void lfrfid_widget_callback(GuiButtonType result, InputType type, void* context) { + LfRfid* app = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(app->view_dispatcher, result); + } +} + +void lfrfid_text_input_callback(void* context) { + LfRfid* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventNext); +} \ No newline at end of file diff --git a/applications/lfrfid/lfrfid_cli.c b/applications/main/lfrfid/lfrfid_cli.c similarity index 99% rename from applications/lfrfid/lfrfid_cli.c rename to applications/main/lfrfid/lfrfid_cli.c index 9a6930a6..281a0e96 100644 --- a/applications/lfrfid/lfrfid_cli.c +++ b/applications/main/lfrfid/lfrfid_cli.c @@ -114,7 +114,7 @@ static void lfrfid_cli_read(Cli* cli, string_t args) { string_t info; string_init(info); protocol_dict_render_data(dict, info, context.protocol); - if(string_size(info) > 0) { + if(!string_empty_p(info)) { printf("%s\r\n", string_get_cstr(info)); } string_clear(info); diff --git a/applications/main/lfrfid/lfrfid_i.h b/applications/main/lfrfid/lfrfid_i.h new file mode 100644 index 00000000..77e87252 --- /dev/null +++ b/applications/main/lfrfid/lfrfid_i.h @@ -0,0 +1,145 @@ +#pragma once + +#include "m-string.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#define LFRFID_KEY_NAME_SIZE 22 +#define LFRFID_TEXT_STORE_SIZE 40 + +#define LFRFID_APP_FOLDER ANY_PATH("lfrfid") +#define LFRFID_SD_FOLDER EXT_PATH("lfrfid") +#define LFRFID_APP_EXTENSION ".rfid" +#define LFRFID_APP_SHADOW_EXTENSION ".shd" + +#define LFRFID_APP_RAW_ASK_EXTENSION ".ask.raw" +#define LFRFID_APP_RAW_PSK_EXTENSION ".psk.raw" + +enum LfRfidCustomEvent { + LfRfidEventNext = 100, + LfRfidEventExit, + LfRfidEventPopupClosed, + LfRfidEventReadSenseStart, + LfRfidEventReadSenseEnd, + LfRfidEventReadSenseCardStart, + LfRfidEventReadSenseCardEnd, + LfRfidEventReadStartASK, + LfRfidEventReadStartPSK, + LfRfidEventReadDone, + LfRfidEventReadOverrun, + LfRfidEventReadError, + LfRfidEventWriteOK, + LfRfidEventWriteProtocolCannotBeWritten, + LfRfidEventWriteFobCannotBeWritten, + LfRfidEventWriteTooLongToWrite, + LfRfidEventRpcLoadFile, + LfRfidEventRpcSessionClose, +}; + +typedef enum { + LfRfidRpcStateIdle, + LfRfidRpcStateEmulating, +} LfRfidRpcState; + +typedef struct LfRfid LfRfid; + +struct LfRfid { + LFRFIDWorker* lfworker; + ViewDispatcher* view_dispatcher; + Gui* gui; + NotificationApp* notifications; + SceneManager* scene_manager; + Storage* storage; + DialogsApp* dialogs; + Widget* widget; + + char text_store[LFRFID_TEXT_STORE_SIZE + 1]; + string_t file_path; + string_t file_name; + string_t raw_file_name; + + ProtocolDict* dict; + ProtocolId protocol_id; + ProtocolId protocol_id_next; + LFRFIDWorkerReadType read_type; + + uint8_t* old_key_data; + uint8_t* new_key_data; + + RpcAppSystem* rpc_ctx; + LfRfidRpcState rpc_state; + + // Common Views + Submenu* submenu; + DialogEx* dialog_ex; + Popup* popup; + TextInput* text_input; + ByteInput* byte_input; + + // Custom views + LfRfidReadView* read_view; +}; + +typedef enum { + LfRfidViewSubmenu, + LfRfidViewDialogEx, + LfRfidViewPopup, + LfRfidViewWidget, + LfRfidViewTextInput, + LfRfidViewByteInput, + LfRfidViewRead, +} LfRfidView; + +bool lfrfid_save_key(LfRfid* app); + +bool lfrfid_load_key_from_file_select(LfRfid* app); + +bool lfrfid_delete_key(LfRfid* app); + +bool lfrfid_load_key_data(LfRfid* app, string_t path, bool show_dialog); + +bool lfrfid_save_key_data(LfRfid* app, string_t path); + +void lfrfid_make_app_folder(LfRfid* app); + +void lfrfid_text_store_set(LfRfid* app, const char* text, ...); + +void lfrfid_text_store_clear(LfRfid* app); + +void lfrfid_popup_timeout_callback(void* context); + +void lfrfid_widget_callback(GuiButtonType result, InputType type, void* context); + +void lfrfid_text_input_callback(void* context); diff --git a/applications/main/lfrfid/scenes/lfrfid_scene.c b/applications/main/lfrfid/scenes/lfrfid_scene.c new file mode 100644 index 00000000..0de5ec36 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene.c @@ -0,0 +1,30 @@ +#include "lfrfid_scene.h" + +// Generate scene on_enter handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const lfrfid_on_enter_handlers[])(void*) = { +#include "lfrfid_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const lfrfid_on_event_handlers[])(void* context, SceneManagerEvent event) = { +#include "lfrfid_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const lfrfid_on_exit_handlers[])(void* context) = { +#include "lfrfid_scene_config.h" +}; +#undef ADD_SCENE + +// Initialize scene handlers configuration structure +const SceneManagerHandlers lfrfid_scene_handlers = { + .on_enter_handlers = lfrfid_on_enter_handlers, + .on_event_handlers = lfrfid_on_event_handlers, + .on_exit_handlers = lfrfid_on_exit_handlers, + .scene_num = LfRfidSceneNum, +}; diff --git a/applications/main/lfrfid/scenes/lfrfid_scene.h b/applications/main/lfrfid/scenes/lfrfid_scene.h new file mode 100644 index 00000000..8ce7da09 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +// Generate scene id and total number +#define ADD_SCENE(prefix, name, id) LfRfidScene##id, +typedef enum { +#include "lfrfid_scene_config.h" + LfRfidSceneNum, +} LfRfidScene; +#undef ADD_SCENE + +extern const SceneManagerHandlers lfrfid_scene_handlers; + +// Generate scene on_enter handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); +#include "lfrfid_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_event handlers declaration +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "lfrfid_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_exit handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); +#include "lfrfid_scene_config.h" +#undef ADD_SCENE diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_config.h b/applications/main/lfrfid/scenes/lfrfid_scene_config.h new file mode 100644 index 00000000..b77ade82 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_config.h @@ -0,0 +1,24 @@ +ADD_SCENE(lfrfid, start, Start) +ADD_SCENE(lfrfid, read, Read) +ADD_SCENE(lfrfid, read_success, ReadSuccess) +ADD_SCENE(lfrfid, retry_confirm, RetryConfirm) +ADD_SCENE(lfrfid, exit_confirm, ExitConfirm) +ADD_SCENE(lfrfid, delete_confirm, DeleteConfirm) +ADD_SCENE(lfrfid, read_key_menu, ReadKeyMenu) +ADD_SCENE(lfrfid, write, Write) +ADD_SCENE(lfrfid, write_success, WriteSuccess) +ADD_SCENE(lfrfid, emulate, Emulate) +ADD_SCENE(lfrfid, save_name, SaveName) +ADD_SCENE(lfrfid, save_success, SaveSuccess) +ADD_SCENE(lfrfid, select_key, SelectKey) +ADD_SCENE(lfrfid, saved_key_menu, SavedKeyMenu) +ADD_SCENE(lfrfid, save_data, SaveData) +ADD_SCENE(lfrfid, save_type, SaveType) +ADD_SCENE(lfrfid, saved_info, SavedInfo) +ADD_SCENE(lfrfid, delete_success, DeleteSuccess) +ADD_SCENE(lfrfid, extra_actions, ExtraActions) +ADD_SCENE(lfrfid, raw_info, RawInfo) +ADD_SCENE(lfrfid, raw_name, RawName) +ADD_SCENE(lfrfid, raw_read, RawRead) +ADD_SCENE(lfrfid, raw_success, RawSuccess) +ADD_SCENE(lfrfid, rpc, Rpc) diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_delete_confirm.c b/applications/main/lfrfid/scenes/lfrfid_scene_delete_confirm.c new file mode 100644 index 00000000..dc1c3df2 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_delete_confirm.c @@ -0,0 +1,68 @@ +#include "../lfrfid_i.h" + +void lfrfid_scene_delete_confirm_on_enter(void* context) { + LfRfid* app = context; + Widget* widget = app->widget; + + string_t tmp_string; + string_init(tmp_string); + + widget_add_button_element(widget, GuiButtonTypeLeft, "Back", lfrfid_widget_callback, app); + widget_add_button_element(widget, GuiButtonTypeRight, "Delete", lfrfid_widget_callback, app); + + string_printf(tmp_string, "Delete %s?", string_get_cstr(app->file_name)); + widget_add_string_element( + widget, 64, 0, AlignCenter, AlignTop, FontPrimary, string_get_cstr(tmp_string)); + + string_reset(tmp_string); + size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); + uint8_t* data = (uint8_t*)malloc(size); + protocol_dict_get_data(app->dict, app->protocol_id, data, size); + for(uint8_t i = 0; i < MIN(size, (size_t)8); i++) { + if(i != 0) { + string_cat_printf(tmp_string, " "); + } + + string_cat_printf(tmp_string, "%02X", data[i]); + } + free(data); + + widget_add_string_element( + widget, 64, 19, AlignCenter, AlignTop, FontSecondary, string_get_cstr(tmp_string)); + widget_add_string_element( + widget, + 64, + 49, + AlignCenter, + AlignBottom, + FontSecondary, + protocol_dict_get_name(app->dict, app->protocol_id)); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget); + string_clear(tmp_string); +} + +bool lfrfid_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + SceneManager* scene_manager = app->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeBack) { + consumed = true; // Ignore Back button presses + } else if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == GuiButtonTypeLeft) { + scene_manager_previous_scene(scene_manager); + } else if(event.event == GuiButtonTypeRight) { + lfrfid_delete_key(app); + scene_manager_next_scene(scene_manager, LfRfidSceneDeleteSuccess); + } + } + + return consumed; +} + +void lfrfid_scene_delete_confirm_on_exit(void* context) { + LfRfid* app = context; + widget_reset(app->widget); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_delete_success.c b/applications/main/lfrfid/scenes/lfrfid_scene_delete_success.c new file mode 100644 index 00000000..f940b9bd --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_delete_success.c @@ -0,0 +1,35 @@ +#include "../lfrfid_i.h" + +void lfrfid_scene_delete_success_on_enter(void* context) { + LfRfid* app = context; + Popup* popup = app->popup; + + popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); + popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); + popup_set_context(popup, app); + popup_set_callback(popup, lfrfid_popup_timeout_callback); + popup_set_timeout(popup, 1500); + popup_enable_timeout(popup); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup); +} + +bool lfrfid_scene_delete_success_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + bool consumed = false; + + if((event.type == SceneManagerEventTypeBack) || + ((event.type == SceneManagerEventTypeCustom) && (event.event == LfRfidEventPopupClosed))) { + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, LfRfidSceneSelectKey); + consumed = true; + } + + return consumed; +} + +void lfrfid_scene_delete_success_on_exit(void* context) { + LfRfid* app = context; + + popup_reset(app->popup); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_emulate.c b/applications/main/lfrfid/scenes/lfrfid_scene_emulate.c new file mode 100644 index 00000000..70cc2418 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_emulate.c @@ -0,0 +1,44 @@ +#include "../lfrfid_i.h" +#include + +void lfrfid_scene_emulate_on_enter(void* context) { + LfRfid* app = context; + Popup* popup = app->popup; + + DOLPHIN_DEED(DolphinDeedRfidEmulate); + + popup_set_header(popup, "Emulating", 89, 30, AlignCenter, AlignTop); + if(!string_empty_p(app->file_name)) { + popup_set_text(popup, string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop); + } else { + popup_set_text( + popup, + protocol_dict_get_name(app->dict, app->protocol_id), + 89, + 43, + AlignCenter, + AlignTop); + } + popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61); + + lfrfid_worker_start_thread(app->lfworker); + lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id); + notification_message(app->notifications, &sequence_blink_start_magenta); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup); +} + +bool lfrfid_scene_emulate_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + bool consumed = false; + return consumed; +} + +void lfrfid_scene_emulate_on_exit(void* context) { + LfRfid* app = context; + notification_message(app->notifications, &sequence_blink_stop); + popup_reset(app->popup); + lfrfid_worker_stop(app->lfworker); + lfrfid_worker_stop_thread(app->lfworker); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_exit_confirm.c b/applications/main/lfrfid/scenes/lfrfid_scene_exit_confirm.c new file mode 100644 index 00000000..e8ab481c --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_exit_confirm.c @@ -0,0 +1,39 @@ +#include "../lfrfid_i.h" + +void lfrfid_scene_exit_confirm_on_enter(void* context) { + LfRfid* app = context; + Widget* widget = app->widget; + + widget_add_button_element(widget, GuiButtonTypeLeft, "Exit", lfrfid_widget_callback, app); + widget_add_button_element(widget, GuiButtonTypeRight, "Stay", lfrfid_widget_callback, app); + widget_add_string_element( + widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Exit to RFID Menu?"); + widget_add_string_element( + widget, 64, 31, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!"); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget); +} + +bool lfrfid_scene_exit_confirm_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + SceneManager* scene_manager = app->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeBack) { + consumed = true; // Ignore Back button presses + } else if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == GuiButtonTypeLeft) { + scene_manager_search_and_switch_to_previous_scene(scene_manager, LfRfidSceneStart); + } else if(event.event == GuiButtonTypeRight) { + scene_manager_previous_scene(scene_manager); + } + } + + return consumed; +} + +void lfrfid_scene_exit_confirm_on_exit(void* context) { + LfRfid* app = context; + widget_reset(app->widget); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c b/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c new file mode 100644 index 00000000..43e3de99 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c @@ -0,0 +1,79 @@ +#include "../lfrfid_i.h" + +typedef enum { + SubmenuIndexASK, + SubmenuIndexPSK, + SubmenuIndexRAW, +} SubmenuIndex; + +static void lfrfid_scene_extra_actions_submenu_callback(void* context, uint32_t index) { + LfRfid* app = context; + + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +void lfrfid_scene_extra_actions_on_enter(void* context) { + LfRfid* app = context; + Submenu* submenu = app->submenu; + + submenu_add_item( + submenu, + "Read ASK (Animal, Ordinary Card)", + SubmenuIndexASK, + lfrfid_scene_extra_actions_submenu_callback, + app); + submenu_add_item( + submenu, + "Read PSK (Indala)", + SubmenuIndexPSK, + lfrfid_scene_extra_actions_submenu_callback, + app); + + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { + submenu_add_item( + submenu, + "Read RAW RFID data", + SubmenuIndexRAW, + lfrfid_scene_extra_actions_submenu_callback, + app); + } + + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneExtraActions)); + + // clear key + string_reset(app->file_name); + app->protocol_id = PROTOCOL_NO; + app->read_type = LFRFIDWorkerReadTypeAuto; + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu); +} + +bool lfrfid_scene_extra_actions_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexASK) { + app->read_type = LFRFIDWorkerReadTypeASKOnly; + scene_manager_next_scene(app->scene_manager, LfRfidSceneRead); + consumed = true; + } else if(event.event == SubmenuIndexPSK) { + app->read_type = LFRFIDWorkerReadTypePSKOnly; + scene_manager_next_scene(app->scene_manager, LfRfidSceneRead); + consumed = true; + } else if(event.event == SubmenuIndexRAW) { + scene_manager_next_scene(app->scene_manager, LfRfidSceneRawName); + consumed = true; + } + scene_manager_set_scene_state(app->scene_manager, LfRfidSceneExtraActions, event.event); + } + + return consumed; +} + +void lfrfid_scene_extra_actions_on_exit(void* context) { + LfRfid* app = context; + + submenu_reset(app->submenu); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_raw_info.c b/applications/main/lfrfid/scenes/lfrfid_scene_raw_info.c new file mode 100644 index 00000000..f60dd624 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_raw_info.c @@ -0,0 +1,64 @@ +#include "../lfrfid_i.h" + +void lfrfid_scene_raw_info_on_enter(void* context) { + LfRfid* app = context; + Widget* widget = app->widget; + + // string_t tmp_string; + // string_init(tmp_string); + + bool sd_exist = storage_sd_status(app->storage) == FSE_OK; + if(!sd_exist) { + widget_add_icon_element(widget, 0, 0, &I_SDQuestion_35x43); + widget_add_string_multiline_element( + widget, + 81, + 4, + AlignCenter, + AlignTop, + FontSecondary, + "No SD card found.\nThis function will not\nwork without\nSD card."); + + widget_add_button_element(widget, GuiButtonTypeLeft, "Back", lfrfid_widget_callback, app); + } else { + widget_add_string_multiline_element( + widget, + 0, + 1, + AlignLeft, + AlignTop, + FontSecondary, + "RAW RFID data reader\n1) Put the Flipper on your card\n2) Press OK\n3) Wait until data is read"); + + widget_add_button_element(widget, GuiButtonTypeCenter, "OK", lfrfid_widget_callback, app); + } + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget); + //string_clear(tmp_string); +} + +bool lfrfid_scene_raw_info_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + SceneManager* scene_manager = app->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeBack) { + consumed = true; + scene_manager_search_and_switch_to_previous_scene(scene_manager, LfRfidSceneExtraActions); + } else if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == GuiButtonTypeCenter) { + scene_manager_next_scene(scene_manager, LfRfidSceneRawRead); + } else if(event.event == GuiButtonTypeLeft) { + scene_manager_search_and_switch_to_previous_scene( + scene_manager, LfRfidSceneExtraActions); + } + } + + return consumed; +} + +void lfrfid_scene_raw_info_on_exit(void* context) { + LfRfid* app = context; + widget_reset(app->widget); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_raw_name.c b/applications/main/lfrfid/scenes/lfrfid_scene_raw_name.c new file mode 100644 index 00000000..512f9ee4 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_raw_name.c @@ -0,0 +1,58 @@ +#include "../lfrfid_i.h" + +void lfrfid_scene_raw_name_on_enter(void* context) { + LfRfid* app = context; + TextInput* text_input = app->text_input; + + const char* key_name = string_get_cstr(app->raw_file_name); + + bool key_name_is_empty = string_empty_p(app->file_name); + if(key_name_is_empty) { + lfrfid_text_store_set(app, "RfidRecord"); + } else { + lfrfid_text_store_set(app, "%s", key_name); + } + + text_input_set_header_text(text_input, "Name the raw file"); + + text_input_set_result_callback( + text_input, + lfrfid_text_input_callback, + app, + app->text_store, + LFRFID_KEY_NAME_SIZE, + key_name_is_empty); + + ValidatorIsFile* validator_is_file = + validator_is_file_alloc_init(LFRFID_SD_FOLDER, LFRFID_APP_RAW_ASK_EXTENSION, NULL); + text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewTextInput); +} + +bool lfrfid_scene_raw_name_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + SceneManager* scene_manager = app->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == LfRfidEventNext) { + consumed = true; + string_set_str(app->raw_file_name, app->text_store); + scene_manager_next_scene(scene_manager, LfRfidSceneRawInfo); + } + } + + return consumed; +} + +void lfrfid_scene_raw_name_on_exit(void* context) { + LfRfid* app = context; + TextInput* text_input = app->text_input; + + void* validator_context = text_input_get_validator_callback_context(text_input); + text_input_set_validator(text_input, NULL, NULL); + validator_is_file_free((ValidatorIsFile*)validator_context); + + text_input_reset(text_input); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_raw_read.c b/applications/main/lfrfid/scenes/lfrfid_scene_raw_read.c new file mode 100644 index 00000000..d0c03ffa --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_raw_read.c @@ -0,0 +1,126 @@ +#include "../lfrfid_i.h" + +#define RAW_READ_TIME 5000 + +typedef struct { + string_t string_file_name; + FuriTimer* timer; + bool is_psk; + bool error; +} LfRfidReadRawState; + +static void lfrfid_read_callback(LFRFIDWorkerReadRawResult result, void* context) { + LfRfid* app = context; + + if(result == LFRFIDWorkerReadRawFileError) { + view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadError); + } else if(result == LFRFIDWorkerReadRawOverrun) { + view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadOverrun); + } +} + +static void timer_callback(void* context) { + LfRfid* app = context; + + view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadDone); +} + +void lfrfid_scene_raw_read_on_enter(void* context) { + LfRfid* app = context; + Popup* popup = app->popup; + + LfRfidReadRawState* state = malloc(sizeof(LfRfidReadRawState)); + scene_manager_set_scene_state(app->scene_manager, LfRfidSceneRawRead, (uint32_t)state); + string_init(state->string_file_name); + + popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61); + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup); + lfrfid_worker_start_thread(app->lfworker); + lfrfid_make_app_folder(app); + + state->timer = furi_timer_alloc(timer_callback, FuriTimerTypeOnce, app); + furi_timer_start(state->timer, RAW_READ_TIME); + string_printf( + state->string_file_name, + "%s/%s%s", + LFRFID_SD_FOLDER, + string_get_cstr(app->raw_file_name), + LFRFID_APP_RAW_ASK_EXTENSION); + popup_set_header(popup, "Reading\nRAW RFID\nASK", 89, 30, AlignCenter, AlignTop); + lfrfid_worker_read_raw_start( + app->lfworker, + string_get_cstr(state->string_file_name), + LFRFIDWorkerReadTypeASKOnly, + lfrfid_read_callback, + app); + + notification_message(app->notifications, &sequence_blink_start_cyan); + + state->is_psk = false; + state->error = false; +} + +bool lfrfid_scene_raw_read_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + Popup* popup = app->popup; + LfRfidReadRawState* state = + (LfRfidReadRawState*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneRawRead); + bool consumed = false; + + furi_assert(state); + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == LfRfidEventReadError) { + consumed = true; + state->error = true; + popup_set_header( + popup, "Reading\nRAW RFID\nFile error", 89, 30, AlignCenter, AlignTop); + notification_message(app->notifications, &sequence_blink_start_red); + furi_timer_stop(state->timer); + } else if(event.event == LfRfidEventReadDone) { + consumed = true; + if(!state->error) { + if(state->is_psk) { + notification_message(app->notifications, &sequence_success); + scene_manager_next_scene(app->scene_manager, LfRfidSceneRawSuccess); + } else { + popup_set_header( + popup, "Reading\nRAW RFID\nPSK", 89, 30, AlignCenter, AlignTop); + notification_message(app->notifications, &sequence_blink_start_yellow); + lfrfid_worker_stop(app->lfworker); + string_printf( + state->string_file_name, + "%s/%s%s", + LFRFID_SD_FOLDER, + string_get_cstr(app->raw_file_name), + LFRFID_APP_RAW_PSK_EXTENSION); + lfrfid_worker_read_raw_start( + app->lfworker, + string_get_cstr(state->string_file_name), + LFRFIDWorkerReadTypePSKOnly, + lfrfid_read_callback, + app); + furi_timer_start(state->timer, RAW_READ_TIME); + state->is_psk = true; + } + } + } + } + + return consumed; +} + +void lfrfid_scene_raw_read_on_exit(void* context) { + LfRfid* app = context; + LfRfidReadRawState* state = + (LfRfidReadRawState*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneRawRead); + + notification_message(app->notifications, &sequence_blink_stop); + popup_reset(app->popup); + lfrfid_worker_stop(app->lfworker); + lfrfid_worker_stop_thread(app->lfworker); + furi_timer_free(state->timer); + + string_clear(state->string_file_name); + free(state); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_raw_success.c b/applications/main/lfrfid/scenes/lfrfid_scene_raw_success.c new file mode 100644 index 00000000..09a00529 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_raw_success.c @@ -0,0 +1,39 @@ +#include "../lfrfid_i.h" + +void lfrfid_scene_raw_success_on_enter(void* context) { + LfRfid* app = context; + Widget* widget = app->widget; + + widget_add_button_element(widget, GuiButtonTypeCenter, "OK", lfrfid_widget_callback, app); + + widget_add_string_multiline_element( + widget, + 0, + 1, + AlignLeft, + AlignTop, + FontSecondary, + "RAW RFID read success!\nNow you can analyze files\nOr send them to developers"); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget); +} + +bool lfrfid_scene_raw_success_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + SceneManager* scene_manager = app->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == GuiButtonTypeCenter) { + scene_manager_search_and_switch_to_previous_scene( + scene_manager, LfRfidSceneExtraActions); + } + } + return consumed; +} + +void lfrfid_scene_raw_success_on_exit(void* context) { + LfRfid* app = context; + widget_reset(app->widget); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_read.c b/applications/main/lfrfid/scenes/lfrfid_scene_read.c new file mode 100644 index 00000000..66168038 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_read.c @@ -0,0 +1,109 @@ +#include "../lfrfid_i.h" +#include + +static const NotificationSequence sequence_blink_set_yellow = { + &message_blink_set_color_yellow, + NULL, +}; + +static const NotificationSequence sequence_blink_set_green = { + &message_blink_set_color_green, + NULL, +}; + +static const NotificationSequence sequence_blink_set_cyan = { + &message_blink_set_color_cyan, + NULL, +}; + +static void + lfrfid_read_callback(LFRFIDWorkerReadResult result, ProtocolId protocol, void* context) { + LfRfid* app = context; + uint32_t event = 0; + + if(result == LFRFIDWorkerReadSenseStart) { + event = LfRfidEventReadSenseStart; + } else if(result == LFRFIDWorkerReadSenseEnd) { + event = LfRfidEventReadSenseEnd; + } else if(result == LFRFIDWorkerReadSenseCardStart) { + event = LfRfidEventReadSenseCardStart; + } else if(result == LFRFIDWorkerReadSenseCardEnd) { + event = LfRfidEventReadSenseCardEnd; + } else if(result == LFRFIDWorkerReadDone) { + event = LfRfidEventReadDone; + app->protocol_id_next = protocol; + } else if(result == LFRFIDWorkerReadStartASK) { + event = LfRfidEventReadStartASK; + } else if(result == LFRFIDWorkerReadStartPSK) { + event = LfRfidEventReadStartPSK; + } else { + return; + } + + view_dispatcher_send_custom_event(app->view_dispatcher, event); +} + +void lfrfid_scene_read_on_enter(void* context) { + LfRfid* app = context; + + DOLPHIN_DEED(DolphinDeedRfidRead); + if(app->read_type == LFRFIDWorkerReadTypePSKOnly) { + lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadPskOnly); + } else if(app->read_type == LFRFIDWorkerReadTypeASKOnly) { + lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadAskOnly); + } + + lfrfid_worker_start_thread(app->lfworker); + lfrfid_worker_read_start(app->lfworker, app->read_type, lfrfid_read_callback, app); + + notification_message(app->notifications, &sequence_blink_start_cyan); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewRead); +} + +bool lfrfid_scene_read_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == LfRfidEventReadSenseStart) { + notification_message(app->notifications, &sequence_blink_set_yellow); + consumed = true; + } else if(event.event == LfRfidEventReadSenseCardStart) { + notification_message(app->notifications, &sequence_blink_set_green); + consumed = true; + } else if( + (event.event == LfRfidEventReadSenseEnd) || + (event.event == LfRfidEventReadSenseCardEnd)) { + notification_message(app->notifications, &sequence_blink_set_cyan); + consumed = true; + } else if(event.event == LfRfidEventReadDone) { + app->protocol_id = app->protocol_id_next; + DOLPHIN_DEED(DolphinDeedRfidReadSuccess); + notification_message(app->notifications, &sequence_success); + string_reset(app->file_name); + scene_manager_next_scene(app->scene_manager, LfRfidSceneReadSuccess); + consumed = true; + } else if(event.event == LfRfidEventReadStartPSK) { + if(app->read_type == LFRFIDWorkerReadTypeAuto) { + lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadPsk); + } + consumed = true; + } else if(event.event == LfRfidEventReadStartASK) { + if(app->read_type == LFRFIDWorkerReadTypeAuto) { + lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadAsk); + } + consumed = true; + } + } + + return consumed; +} + +void lfrfid_scene_read_on_exit(void* context) { + LfRfid* app = context; + notification_message(app->notifications, &sequence_blink_stop); + popup_reset(app->popup); + lfrfid_worker_stop(app->lfworker); + lfrfid_worker_stop_thread(app->lfworker); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_read_key_menu.c b/applications/main/lfrfid/scenes/lfrfid_scene_read_key_menu.c new file mode 100644 index 00000000..221cc008 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_read_key_menu.c @@ -0,0 +1,58 @@ +#include "../lfrfid_i.h" + +typedef enum { + SubmenuIndexSave, + SubmenuIndexEmulate, + SubmenuIndexWrite, +} SubmenuIndex; + +void lfrfid_scene_read_key_menu_submenu_callback(void* context, uint32_t index) { + LfRfid* app = context; + + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +void lfrfid_scene_read_key_menu_on_enter(void* context) { + LfRfid* app = context; + Submenu* submenu = app->submenu; + + submenu_add_item( + submenu, "Save", SubmenuIndexSave, lfrfid_scene_read_key_menu_submenu_callback, app); + submenu_add_item( + submenu, "Emulate", SubmenuIndexEmulate, lfrfid_scene_read_key_menu_submenu_callback, app); + submenu_add_item( + submenu, "Write", SubmenuIndexWrite, lfrfid_scene_read_key_menu_submenu_callback, app); + + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneReadKeyMenu)); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu); +} + +bool lfrfid_scene_read_key_menu_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexWrite) { + scene_manager_next_scene(app->scene_manager, LfRfidSceneWrite); + consumed = true; + } else if(event.event == SubmenuIndexSave) { + string_reset(app->file_name); + scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveName); + consumed = true; + } else if(event.event == SubmenuIndexEmulate) { + scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate); + consumed = true; + } + scene_manager_set_scene_state(app->scene_manager, LfRfidSceneReadKeyMenu, event.event); + } + + return consumed; +} + +void lfrfid_scene_read_key_menu_on_exit(void* context) { + LfRfid* app = context; + + submenu_reset(app->submenu); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_read_success.c b/applications/main/lfrfid/scenes/lfrfid_scene_read_success.c new file mode 100644 index 00000000..5ae6f0f1 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_read_success.c @@ -0,0 +1,78 @@ +#include "../lfrfid_i.h" + +void lfrfid_scene_read_success_on_enter(void* context) { + LfRfid* app = context; + Widget* widget = app->widget; + + string_t tmp_string; + string_init(tmp_string); + + widget_add_button_element(widget, GuiButtonTypeLeft, "Retry", lfrfid_widget_callback, app); + widget_add_button_element(widget, GuiButtonTypeRight, "More", lfrfid_widget_callback, app); + + string_printf( + tmp_string, + "%s[%s]", + protocol_dict_get_name(app->dict, app->protocol_id), + protocol_dict_get_manufacturer(app->dict, app->protocol_id)); + + widget_add_string_element( + widget, 0, 2, AlignLeft, AlignTop, FontPrimary, string_get_cstr(tmp_string)); + + string_reset(tmp_string); + size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); + uint8_t* data = (uint8_t*)malloc(size); + protocol_dict_get_data(app->dict, app->protocol_id, data, size); + for(uint8_t i = 0; i < size; i++) { + if(i >= 9) { + string_cat_printf(tmp_string, ".."); + break; + } else { + if(i != 0) { + string_cat_printf(tmp_string, " "); + } + string_cat_printf(tmp_string, "%02X", data[i]); + } + } + free(data); + + string_t render_data; + string_init(render_data); + protocol_dict_render_brief_data(app->dict, render_data, app->protocol_id); + string_cat_printf(tmp_string, "\r\n%s", string_get_cstr(render_data)); + string_clear(render_data); + + widget_add_string_multiline_element( + widget, 0, 16, AlignLeft, AlignTop, FontSecondary, string_get_cstr(tmp_string)); + + notification_message_block(app->notifications, &sequence_set_green_255); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget); + string_clear(tmp_string); +} + +bool lfrfid_scene_read_success_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + SceneManager* scene_manager = app->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeBack) { + scene_manager_next_scene(scene_manager, LfRfidSceneExitConfirm); + consumed = true; + } else if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == GuiButtonTypeLeft) { + scene_manager_next_scene(scene_manager, LfRfidSceneRetryConfirm); + } else if(event.event == GuiButtonTypeRight) { + scene_manager_next_scene(scene_manager, LfRfidSceneReadKeyMenu); + } + } + + return consumed; +} + +void lfrfid_scene_read_success_on_exit(void* context) { + LfRfid* app = context; + notification_message_block(app->notifications, &sequence_reset_green); + widget_reset(app->widget); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_retry_confirm.c b/applications/main/lfrfid/scenes/lfrfid_scene_retry_confirm.c new file mode 100644 index 00000000..f639f0ae --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_retry_confirm.c @@ -0,0 +1,39 @@ +#include "../lfrfid_i.h" + +void lfrfid_scene_retry_confirm_on_enter(void* context) { + LfRfid* app = context; + Widget* widget = app->widget; + + widget_add_button_element(widget, GuiButtonTypeLeft, "Exit", lfrfid_widget_callback, app); + widget_add_button_element(widget, GuiButtonTypeRight, "Stay", lfrfid_widget_callback, app); + widget_add_string_element( + widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Return to reading?"); + widget_add_string_element( + widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!"); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget); +} + +bool lfrfid_scene_retry_confirm_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + SceneManager* scene_manager = app->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeBack) { + consumed = true; // Ignore Back button presses + } else if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == GuiButtonTypeLeft) { + scene_manager_search_and_switch_to_previous_scene(scene_manager, LfRfidSceneRead); + } else if(event.event == GuiButtonTypeRight) { + scene_manager_previous_scene(scene_manager); + } + } + + return consumed; +} + +void lfrfid_scene_retry_confirm_on_exit(void* context) { + LfRfid* app = context; + widget_reset(app->widget); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c b/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c new file mode 100644 index 00000000..a69d6453 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c @@ -0,0 +1,67 @@ +#include "../lfrfid_i.h" + +void lfrfid_scene_rpc_on_enter(void* context) { + LfRfid* app = context; + Popup* popup = app->popup; + + popup_set_header(popup, "LF RFID", 89, 42, AlignCenter, AlignBottom); + popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup); + + notification_message(app->notifications, &sequence_display_backlight_on); + + app->rpc_state = LfRfidRpcStateIdle; +} + +bool lfrfid_scene_rpc_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + Popup* popup = app->popup; + UNUSED(event); + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == LfRfidEventExit) { + rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true); + scene_manager_stop(app->scene_manager); + view_dispatcher_stop(app->view_dispatcher); + } else if(event.event == LfRfidEventRpcSessionClose) { + scene_manager_stop(app->scene_manager); + view_dispatcher_stop(app->view_dispatcher); + } else if(event.event == LfRfidEventRpcLoadFile) { + const char* arg = rpc_system_app_get_data(app->rpc_ctx); + bool result = false; + if(arg && (app->rpc_state == LfRfidRpcStateIdle)) { + string_set_str(app->file_path, arg); + if(lfrfid_load_key_data(app, app->file_path, false)) { + lfrfid_worker_start_thread(app->lfworker); + lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id); + app->rpc_state = LfRfidRpcStateEmulating; + + lfrfid_text_store_set(app, "emulating\n%s", string_get_cstr(app->file_name)); + popup_set_text(popup, app->text_store, 89, 44, AlignCenter, AlignTop); + + notification_message(app->notifications, &sequence_blink_start_magenta); + result = true; + } + } + rpc_system_app_confirm(app->rpc_ctx, RpcAppEventLoadFile, result); + } + } + return consumed; +} + +void lfrfid_scene_rpc_on_exit(void* context) { + LfRfid* app = context; + Popup* popup = app->popup; + + if(app->rpc_state == LfRfidRpcStateEmulating) { + lfrfid_worker_stop(app->lfworker); + lfrfid_worker_stop_thread(app->lfworker); + notification_message(app->notifications, &sequence_blink_stop); + } + + popup_reset(popup); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_save_data.c b/applications/main/lfrfid/scenes/lfrfid_scene_save_data.c new file mode 100644 index 00000000..2ca1bb43 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_save_data.c @@ -0,0 +1,51 @@ +#include "../lfrfid_i.h" +#include + +void lfrfid_scene_save_data_on_enter(void* context) { + LfRfid* app = context; + ByteInput* byte_input = app->byte_input; + + size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); + + bool need_restore = scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveData); + + if(need_restore) { + protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size); + } else { + protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size); + } + + protocol_dict_get_data(app->dict, app->protocol_id, app->new_key_data, size); + + byte_input_set_header_text(byte_input, "Enter the data in hex"); + + byte_input_set_result_callback( + byte_input, lfrfid_text_input_callback, NULL, app, app->new_key_data, size); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewByteInput); +} + +bool lfrfid_scene_save_data_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + SceneManager* scene_manager = app->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == LfRfidEventNext) { + consumed = true; + size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); + protocol_dict_set_data(app->dict, app->protocol_id, app->new_key_data, size); + DOLPHIN_DEED(DolphinDeedRfidAdd); + scene_manager_next_scene(scene_manager, LfRfidSceneSaveName); + scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 1); + } + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 0); + } + + return consumed; +} + +void lfrfid_scene_save_data_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_save_name.c b/applications/main/lfrfid/scenes/lfrfid_scene_save_name.c new file mode 100644 index 00000000..febf30a4 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_save_name.c @@ -0,0 +1,76 @@ +#include "m-string.h" +#include +#include "../lfrfid_i.h" + +void lfrfid_scene_save_name_on_enter(void* context) { + LfRfid* app = context; + TextInput* text_input = app->text_input; + string_t folder_path; + string_init(folder_path); + + bool key_name_is_empty = string_empty_p(app->file_name); + if(key_name_is_empty) { + string_set_str(app->file_path, LFRFID_APP_FOLDER); + set_random_name(app->text_store, LFRFID_TEXT_STORE_SIZE); + string_set_str(folder_path, LFRFID_APP_FOLDER); + } else { + lfrfid_text_store_set(app, "%s", string_get_cstr(app->file_name)); + path_extract_dirname(string_get_cstr(app->file_path), folder_path); + } + + text_input_set_header_text(text_input, "Name the card"); + text_input_set_result_callback( + text_input, + lfrfid_text_input_callback, + app, + app->text_store, + LFRFID_KEY_NAME_SIZE, + key_name_is_empty); + + FURI_LOG_I("", "%s %s", string_get_cstr(folder_path), app->text_store); + + ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( + string_get_cstr(folder_path), LFRFID_APP_EXTENSION, string_get_cstr(app->file_name)); + text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + + string_clear(folder_path); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewTextInput); +} + +bool lfrfid_scene_save_name_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + SceneManager* scene_manager = app->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == LfRfidEventNext) { + consumed = true; + if(!string_empty_p(app->file_name)) { + lfrfid_delete_key(app); + } + + string_set_str(app->file_name, app->text_store); + + if(lfrfid_save_key(app)) { + scene_manager_next_scene(scene_manager, LfRfidSceneSaveSuccess); + } else { + scene_manager_search_and_switch_to_previous_scene( + scene_manager, LfRfidSceneReadKeyMenu); + } + } + } + + return consumed; +} + +void lfrfid_scene_save_name_on_exit(void* context) { + LfRfid* app = context; + TextInput* text_input = app->text_input; + + void* validator_context = text_input_get_validator_callback_context(text_input); + text_input_set_validator(text_input, NULL, NULL); + validator_is_file_free((ValidatorIsFile*)validator_context); + + text_input_reset(text_input); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_save_success.c b/applications/main/lfrfid/scenes/lfrfid_scene_save_success.c new file mode 100644 index 00000000..830ef336 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_save_success.c @@ -0,0 +1,43 @@ +#include "../lfrfid_i.h" +#include + +void lfrfid_scene_save_success_on_enter(void* context) { + LfRfid* app = context; + Popup* popup = app->popup; + + DOLPHIN_DEED(DolphinDeedRfidSave); + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); + popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); + popup_set_context(popup, app); + popup_set_callback(popup, lfrfid_popup_timeout_callback); + popup_set_timeout(popup, 1500); + popup_enable_timeout(popup); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup); +} + +bool lfrfid_scene_save_success_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + bool consumed = false; + + const uint32_t prev_scenes[] = {LfRfidSceneReadKeyMenu, LfRfidSceneSelectKey}; + + if((event.type == SceneManagerEventTypeBack) || + ((event.type == SceneManagerEventTypeCustom) && (event.event == LfRfidEventPopupClosed))) { + bool result = scene_manager_search_and_switch_to_previous_scene_one_of( + app->scene_manager, prev_scenes, COUNT_OF(prev_scenes)); + if(!result) { + scene_manager_search_and_switch_to_another_scene( + app->scene_manager, LfRfidSceneSelectKey); + } + consumed = true; + } + + return consumed; +} + +void lfrfid_scene_save_success_on_exit(void* context) { + LfRfid* app = context; + + popup_reset(app->popup); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_save_type.c b/applications/main/lfrfid/scenes/lfrfid_scene_save_type.c new file mode 100644 index 00000000..4c111600 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_save_type.c @@ -0,0 +1,86 @@ +#include "../lfrfid_i.h" + +typedef struct { + string_t menu_item_name[LFRFIDProtocolMax]; + uint32_t line_sel; +} SaveTypeCtx; + +static void lfrfid_scene_save_type_submenu_callback(void* context, uint32_t index) { + LfRfid* app = context; + + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +void lfrfid_scene_save_type_on_enter(void* context) { + LfRfid* app = context; + Submenu* submenu = app->submenu; + + SaveTypeCtx* state = malloc(sizeof(SaveTypeCtx)); + for(uint8_t i = 0; i < LFRFIDProtocolMax; i++) { + if(strcmp( + protocol_dict_get_manufacturer(app->dict, i), + protocol_dict_get_name(app->dict, i)) != 0) { + string_init_printf( + state->menu_item_name[i], + "%s %s", + protocol_dict_get_manufacturer(app->dict, i), + protocol_dict_get_name(app->dict, i)); + } else { + string_init_printf( + state->menu_item_name[i], "%s", protocol_dict_get_name(app->dict, i)); + } + submenu_add_item( + submenu, + string_get_cstr(state->menu_item_name[i]), + i, + lfrfid_scene_save_type_submenu_callback, + app); + } + + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveType)); + + scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSaveType, (uint32_t)state); + + // clear key name + string_reset(app->file_name); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu); +} + +bool lfrfid_scene_save_type_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + bool consumed = false; + + SaveTypeCtx* state = + (SaveTypeCtx*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveType); + furi_check(state); + + if(event.type == SceneManagerEventTypeCustom) { + app->protocol_id = event.event; + state->line_sel = event.event; + scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveData); + consumed = true; + } + + return consumed; +} + +void lfrfid_scene_save_type_on_exit(void* context) { + LfRfid* app = context; + SaveTypeCtx* state = + (SaveTypeCtx*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveType); + furi_check(state); + + submenu_reset(app->submenu); + + for(uint8_t i = 0; i < LFRFIDProtocolMax; i++) { + string_clear(state->menu_item_name[i]); + } + + uint32_t line_sel = state->line_sel; + + free(state); + + scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSaveType, line_sel); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_saved_info.c b/applications/main/lfrfid/scenes/lfrfid_scene_saved_info.c new file mode 100644 index 00000000..1496c6b4 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_saved_info.c @@ -0,0 +1,51 @@ +#include "../lfrfid_i.h" + +void lfrfid_scene_saved_info_on_enter(void* context) { + LfRfid* app = context; + Widget* widget = app->widget; + + string_t tmp_string; + string_init(tmp_string); + + string_printf( + tmp_string, + "%s [%s]\r\n", + string_get_cstr(app->file_name), + protocol_dict_get_name(app->dict, app->protocol_id)); + + size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); + uint8_t* data = (uint8_t*)malloc(size); + protocol_dict_get_data(app->dict, app->protocol_id, data, size); + for(uint8_t i = 0; i < size; i++) { + if(i != 0) { + string_cat_printf(tmp_string, " "); + } + + string_cat_printf(tmp_string, "%02X", data[i]); + } + free(data); + + string_t render_data; + string_init(render_data); + protocol_dict_render_data(app->dict, render_data, app->protocol_id); + string_cat_printf(tmp_string, "\r\n%s", string_get_cstr(render_data)); + string_clear(render_data); + + widget_add_string_multiline_element( + widget, 0, 1, AlignLeft, AlignTop, FontSecondary, string_get_cstr(tmp_string)); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget); + string_clear(tmp_string); +} + +bool lfrfid_scene_saved_info_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + bool consumed = false; + return consumed; +} + +void lfrfid_scene_saved_info_on_exit(void* context) { + LfRfid* app = context; + widget_reset(app->widget); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_saved_key_menu.c b/applications/main/lfrfid/scenes/lfrfid_scene_saved_key_menu.c new file mode 100644 index 00000000..040b31f1 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_saved_key_menu.c @@ -0,0 +1,69 @@ +#include "../lfrfid_i.h" + +typedef enum { + SubmenuIndexEmulate, + SubmenuIndexWrite, + SubmenuIndexEdit, + SubmenuIndexDelete, + SubmenuIndexInfo, +} SubmenuIndex; + +static void lfrfid_scene_saved_key_menu_submenu_callback(void* context, uint32_t index) { + LfRfid* app = context; + + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +void lfrfid_scene_saved_key_menu_on_enter(void* context) { + LfRfid* app = context; + Submenu* submenu = app->submenu; + + submenu_add_item( + submenu, "Emulate", SubmenuIndexEmulate, lfrfid_scene_saved_key_menu_submenu_callback, app); + submenu_add_item( + submenu, "Write", SubmenuIndexWrite, lfrfid_scene_saved_key_menu_submenu_callback, app); + submenu_add_item( + submenu, "Edit", SubmenuIndexEdit, lfrfid_scene_saved_key_menu_submenu_callback, app); + submenu_add_item( + submenu, "Delete", SubmenuIndexDelete, lfrfid_scene_saved_key_menu_submenu_callback, app); + submenu_add_item( + submenu, "Info", SubmenuIndexInfo, lfrfid_scene_saved_key_menu_submenu_callback, app); + + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSavedKeyMenu)); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu); +} + +bool lfrfid_scene_saved_key_menu_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexEmulate) { + scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate); + consumed = true; + } else if(event.event == SubmenuIndexWrite) { + scene_manager_next_scene(app->scene_manager, LfRfidSceneWrite); + consumed = true; + } else if(event.event == SubmenuIndexEdit) { + scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveData); + consumed = true; + } else if(event.event == SubmenuIndexDelete) { + scene_manager_next_scene(app->scene_manager, LfRfidSceneDeleteConfirm); + consumed = true; + } else if(event.event == SubmenuIndexInfo) { + scene_manager_next_scene(app->scene_manager, LfRfidSceneSavedInfo); + consumed = true; + } + scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSavedKeyMenu, event.event); + } + + return consumed; +} + +void lfrfid_scene_saved_key_menu_on_exit(void* context) { + LfRfid* app = context; + + submenu_reset(app->submenu); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_select_key.c b/applications/main/lfrfid/scenes/lfrfid_scene_select_key.c new file mode 100644 index 00000000..2a9cc1c6 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_select_key.c @@ -0,0 +1,22 @@ +#include "../lfrfid_i.h" + +void lfrfid_scene_select_key_on_enter(void* context) { + LfRfid* app = context; + + if(lfrfid_load_key_from_file_select(app)) { + scene_manager_next_scene(app->scene_manager, LfRfidSceneSavedKeyMenu); + } else { + scene_manager_previous_scene(app->scene_manager); + } +} + +bool lfrfid_scene_select_key_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + bool consumed = false; + return consumed; +} + +void lfrfid_scene_select_key_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_start.c b/applications/main/lfrfid/scenes/lfrfid_scene_start.c new file mode 100644 index 00000000..9074e859 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_start.c @@ -0,0 +1,72 @@ +#include "../lfrfid_i.h" + +typedef enum { + SubmenuIndexRead, + SubmenuIndexSaved, + SubmenuIndexAddManually, + SubmenuIndexExtraActions, +} SubmenuIndex; + +static void lfrfid_scene_start_submenu_callback(void* context, uint32_t index) { + LfRfid* app = context; + + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +void lfrfid_scene_start_on_enter(void* context) { + LfRfid* app = context; + Submenu* submenu = app->submenu; + + submenu_add_item(submenu, "Read", SubmenuIndexRead, lfrfid_scene_start_submenu_callback, app); + submenu_add_item( + submenu, "Saved", SubmenuIndexSaved, lfrfid_scene_start_submenu_callback, app); + submenu_add_item( + submenu, "Add Manually", SubmenuIndexAddManually, lfrfid_scene_start_submenu_callback, app); + submenu_add_item( + submenu, + "Extra Actions", + SubmenuIndexExtraActions, + lfrfid_scene_start_submenu_callback, + app); + + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneStart)); + + // clear key + string_reset(app->file_name); + app->protocol_id = PROTOCOL_NO; + app->read_type = LFRFIDWorkerReadTypeAuto; + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu); +} + +bool lfrfid_scene_start_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexRead) { + scene_manager_next_scene(app->scene_manager, LfRfidSceneRead); + consumed = true; + } else if(event.event == SubmenuIndexSaved) { + string_set_str(app->file_path, LFRFID_APP_FOLDER); + scene_manager_next_scene(app->scene_manager, LfRfidSceneSelectKey); + consumed = true; + } else if(event.event == SubmenuIndexAddManually) { + scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveType); + consumed = true; + } else if(event.event == SubmenuIndexExtraActions) { + scene_manager_next_scene(app->scene_manager, LfRfidSceneExtraActions); + consumed = true; + } + scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, event.event); + } + + return consumed; +} + +void lfrfid_scene_start_on_exit(void* context) { + LfRfid* app = context; + + submenu_reset(app->submenu); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_write.c b/applications/main/lfrfid/scenes/lfrfid_scene_write.c new file mode 100644 index 00000000..4b03bac1 --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_write.c @@ -0,0 +1,96 @@ +#include "../lfrfid_i.h" + +static void lfrfid_write_callback(LFRFIDWorkerWriteResult result, void* context) { + LfRfid* app = context; + uint32_t event = 0; + + if(result == LFRFIDWorkerWriteOK) { + event = LfRfidEventWriteOK; + } else if(result == LFRFIDWorkerWriteProtocolCannotBeWritten) { + event = LfRfidEventWriteProtocolCannotBeWritten; + } else if(result == LFRFIDWorkerWriteFobCannotBeWritten) { + event = LfRfidEventWriteFobCannotBeWritten; + } else if(result == LFRFIDWorkerWriteTooLongToWrite) { + event = LfRfidEventWriteTooLongToWrite; + } + + view_dispatcher_send_custom_event(app->view_dispatcher, event); +} + +void lfrfid_scene_write_on_enter(void* context) { + LfRfid* app = context; + Popup* popup = app->popup; + + popup_set_header(popup, "Writing", 89, 30, AlignCenter, AlignTop); + if(!string_empty_p(app->file_name)) { + popup_set_text(popup, string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop); + } else { + popup_set_text( + popup, + protocol_dict_get_name(app->dict, app->protocol_id), + 89, + 43, + AlignCenter, + AlignTop); + } + popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup); + + size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); + app->old_key_data = (uint8_t*)malloc(size); + protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size); + + lfrfid_worker_start_thread(app->lfworker); + lfrfid_worker_write_start( + app->lfworker, (LFRFIDProtocol)app->protocol_id, lfrfid_write_callback, app); + notification_message(app->notifications, &sequence_blink_start_magenta); +} + +bool lfrfid_scene_write_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + Popup* popup = app->popup; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == LfRfidEventWriteOK) { + notification_message(app->notifications, &sequence_success); + scene_manager_next_scene(app->scene_manager, LfRfidSceneWriteSuccess); + consumed = true; + } else if(event.event == LfRfidEventWriteProtocolCannotBeWritten) { + popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48); + popup_set_header(popup, "Error", 64, 3, AlignCenter, AlignTop); + popup_set_text(popup, "This protocol\ncannot be written", 3, 17, AlignLeft, AlignTop); + notification_message(app->notifications, &sequence_blink_start_red); + consumed = true; + } else if( + (event.event == LfRfidEventWriteFobCannotBeWritten) || + (event.event == LfRfidEventWriteTooLongToWrite)) { + popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48); + popup_set_header(popup, "Still trying to write...", 64, 3, AlignCenter, AlignTop); + popup_set_text( + popup, + "Make sure this\ncard is writable\nand not\nprotected.", + 3, + 17, + AlignLeft, + AlignTop); + notification_message(app->notifications, &sequence_blink_start_yellow); + consumed = true; + } + } + + return consumed; +} + +void lfrfid_scene_write_on_exit(void* context) { + LfRfid* app = context; + notification_message(app->notifications, &sequence_blink_stop); + popup_reset(app->popup); + lfrfid_worker_stop(app->lfworker); + lfrfid_worker_stop_thread(app->lfworker); + + size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id); + protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size); + free(app->old_key_data); +} diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_write_success.c b/applications/main/lfrfid/scenes/lfrfid_scene_write_success.c new file mode 100644 index 00000000..52e30d6b --- /dev/null +++ b/applications/main/lfrfid/scenes/lfrfid_scene_write_success.c @@ -0,0 +1,38 @@ +#include "../lfrfid_i.h" + +void lfrfid_scene_write_success_on_enter(void* context) { + LfRfid* app = context; + Popup* popup = app->popup; + + popup_set_header(popup, "Successfully\nwritten!", 94, 3, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 6, &I_RFIDDolphinSuccess_108x57); + popup_set_context(popup, app); + popup_set_callback(popup, lfrfid_popup_timeout_callback); + popup_set_timeout(popup, 1500); + popup_enable_timeout(popup); + + view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup); + notification_message_block(app->notifications, &sequence_set_green_255); +} + +bool lfrfid_scene_write_success_on_event(void* context, SceneManagerEvent event) { + LfRfid* app = context; + bool consumed = false; + + const uint32_t prev_scenes[] = {LfRfidSceneReadKeyMenu, LfRfidSceneSelectKey}; + + if((event.type == SceneManagerEventTypeBack) || + ((event.type == SceneManagerEventTypeCustom) && (event.event == LfRfidEventPopupClosed))) { + scene_manager_search_and_switch_to_previous_scene_one_of( + app->scene_manager, prev_scenes, COUNT_OF(prev_scenes)); + consumed = true; + } + + return consumed; +} + +void lfrfid_scene_write_success_on_exit(void* context) { + LfRfid* app = context; + notification_message_block(app->notifications, &sequence_reset_green); + popup_reset(app->popup); +} diff --git a/applications/main/lfrfid/views/lfrfid_view_read.c b/applications/main/lfrfid/views/lfrfid_view_read.c new file mode 100644 index 00000000..66caf8df --- /dev/null +++ b/applications/main/lfrfid/views/lfrfid_view_read.c @@ -0,0 +1,117 @@ +#include "lfrfid_view_read.h" +#include + +#define TEMP_STR_LEN 128 + +struct LfRfidReadView { + View* view; +}; + +typedef struct { + IconAnimation* icon; + LfRfidReadViewMode read_mode; +} LfRfidReadViewModel; + +static void lfrfid_view_read_draw_callback(Canvas* canvas, void* _model) { + LfRfidReadViewModel* model = _model; + canvas_set_color(canvas, ColorBlack); + + canvas_draw_icon(canvas, 0, 8, &I_NFC_manual_60x50); + + canvas_set_font(canvas, FontPrimary); + + if(model->read_mode == LfRfidReadAsk) { + canvas_draw_str(canvas, 70, 16, "Reading 1/2"); + + canvas_draw_str(canvas, 77, 29, "ASK"); + canvas_draw_icon(canvas, 70, 22, &I_ButtonRight_4x7); + canvas_draw_icon_animation(canvas, 102, 21, model->icon); + + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 77, 43, "PSK"); + } else if(model->read_mode == LfRfidReadPsk) { + canvas_draw_str(canvas, 70, 16, "Reading 2/2"); + + canvas_draw_str(canvas, 77, 43, "PSK"); + canvas_draw_icon(canvas, 70, 36, &I_ButtonRight_4x7); + canvas_draw_icon_animation(canvas, 102, 35, model->icon); + + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 77, 29, "ASK"); + } else { + canvas_draw_str(canvas, 72, 16, "Reading"); + + if(model->read_mode == LfRfidReadAskOnly) { + canvas_draw_str(canvas, 77, 35, "ASK"); + } else { + canvas_draw_str(canvas, 77, 35, "PSK"); + } + canvas_draw_icon_animation(canvas, 102, 27, model->icon); + } + + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 61, 56, "Don't move card"); +} + +void lfrfid_view_read_enter(void* context) { + LfRfidReadView* read_view = context; + with_view_model( + read_view->view, (LfRfidReadViewModel * model) { + icon_animation_start(model->icon); + return true; + }); +} + +void lfrfid_view_read_exit(void* context) { + LfRfidReadView* read_view = context; + with_view_model( + read_view->view, (LfRfidReadViewModel * model) { + icon_animation_stop(model->icon); + return false; + }); +} + +LfRfidReadView* lfrfid_view_read_alloc() { + LfRfidReadView* read_view = malloc(sizeof(LfRfidReadView)); + read_view->view = view_alloc(); + view_set_context(read_view->view, read_view); + view_allocate_model(read_view->view, ViewModelTypeLocking, sizeof(LfRfidReadViewModel)); + + with_view_model( + read_view->view, (LfRfidReadViewModel * model) { + model->icon = icon_animation_alloc(&A_Round_loader_8x8); + view_tie_icon_animation(read_view->view, model->icon); + return false; + }); + + view_set_draw_callback(read_view->view, lfrfid_view_read_draw_callback); + view_set_enter_callback(read_view->view, lfrfid_view_read_enter); + view_set_exit_callback(read_view->view, lfrfid_view_read_exit); + + return read_view; +} + +void lfrfid_view_read_free(LfRfidReadView* read_view) { + with_view_model( + read_view->view, (LfRfidReadViewModel * model) { + icon_animation_free(model->icon); + return false; + }); + + view_free(read_view->view); + free(read_view); +} + +View* lfrfid_view_read_get_view(LfRfidReadView* read_view) { + return read_view->view; +} + +void lfrfid_view_read_set_read_mode(LfRfidReadView* read_view, LfRfidReadViewMode mode) { + with_view_model( + read_view->view, (LfRfidReadViewModel * model) { + icon_animation_stop(model->icon); + icon_animation_start(model->icon); + model->read_mode = mode; + return true; + }); +} diff --git a/applications/main/lfrfid/views/lfrfid_view_read.h b/applications/main/lfrfid/views/lfrfid_view_read.h new file mode 100644 index 00000000..55bb1f23 --- /dev/null +++ b/applications/main/lfrfid/views/lfrfid_view_read.h @@ -0,0 +1,19 @@ +#pragma once +#include + +typedef enum { + LfRfidReadAsk, + LfRfidReadPsk, + LfRfidReadAskOnly, + LfRfidReadPskOnly +} LfRfidReadViewMode; + +typedef struct LfRfidReadView LfRfidReadView; + +LfRfidReadView* lfrfid_view_read_alloc(); + +void lfrfid_view_read_free(LfRfidReadView* read_view); + +View* lfrfid_view_read_get_view(LfRfidReadView* read_view); + +void lfrfid_view_read_set_read_mode(LfRfidReadView* read_view, LfRfidReadViewMode mode); diff --git a/applications/nfc/application.fam b/applications/main/nfc/application.fam similarity index 100% rename from applications/nfc/application.fam rename to applications/main/nfc/application.fam diff --git a/applications/nfc/helpers/nfc_custom_event.h b/applications/main/nfc/helpers/nfc_custom_event.h similarity index 100% rename from applications/nfc/helpers/nfc_custom_event.h rename to applications/main/nfc/helpers/nfc_custom_event.h diff --git a/applications/nfc/helpers/nfc_emv_parser.c b/applications/main/nfc/helpers/nfc_emv_parser.c similarity index 100% rename from applications/nfc/helpers/nfc_emv_parser.c rename to applications/main/nfc/helpers/nfc_emv_parser.c diff --git a/applications/nfc/helpers/nfc_emv_parser.h b/applications/main/nfc/helpers/nfc_emv_parser.h similarity index 100% rename from applications/nfc/helpers/nfc_emv_parser.h rename to applications/main/nfc/helpers/nfc_emv_parser.h diff --git a/applications/nfc/helpers/nfc_generators.c b/applications/main/nfc/helpers/nfc_generators.c similarity index 100% rename from applications/nfc/helpers/nfc_generators.c rename to applications/main/nfc/helpers/nfc_generators.c diff --git a/applications/nfc/helpers/nfc_generators.h b/applications/main/nfc/helpers/nfc_generators.h similarity index 100% rename from applications/nfc/helpers/nfc_generators.h rename to applications/main/nfc/helpers/nfc_generators.h diff --git a/applications/nfc/nfc.c b/applications/main/nfc/nfc.c similarity index 89% rename from applications/nfc/nfc.c rename to applications/main/nfc/nfc.c index 57e25f81..f47a5bac 100644 --- a/applications/nfc/nfc.c +++ b/applications/main/nfc/nfc.c @@ -201,8 +201,16 @@ void nfc_text_store_clear(Nfc* nfc) { memset(nfc->text_store, 0, sizeof(nfc->text_store)); } -void nfc_blink_start(Nfc* nfc) { - notification_message(nfc->notifications, &sequence_blink_start_blue); +void nfc_blink_read_start(Nfc* nfc) { + notification_message(nfc->notifications, &sequence_blink_start_cyan); +} + +void nfc_blink_emulate_start(Nfc* nfc) { + notification_message(nfc->notifications, &sequence_blink_start_magenta); +} + +void nfc_blink_detect_start(Nfc* nfc) { + notification_message(nfc->notifications, &sequence_blink_start_yellow); } void nfc_blink_stop(Nfc* nfc) { @@ -223,7 +231,30 @@ void nfc_show_loading_popup(void* context, bool show) { } } +static bool nfc_is_hal_ready() { + if(!furi_hal_nfc_is_init()) { + // No connection to the chip, show an error screen + DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_text( + message, + "Error!\nNFC chip failed to start\n\n\nSend a photo of this to:\nsupport@flipperzero.one", + 0, + 0, + AlignLeft, + AlignTop); + dialog_message_show(dialogs, message); + dialog_message_free(message); + furi_record_close(RECORD_DIALOGS); + return false; + } else { + return true; + } +} + int32_t nfc_app(void* p) { + if(!nfc_is_hal_ready()) return 0; + Nfc* nfc = nfc_alloc(); char* args = p; diff --git a/applications/nfc/nfc.h b/applications/main/nfc/nfc.h similarity index 100% rename from applications/nfc/nfc.h rename to applications/main/nfc/nfc.h diff --git a/applications/nfc/nfc_cli.c b/applications/main/nfc/nfc_cli.c similarity index 100% rename from applications/nfc/nfc_cli.c rename to applications/main/nfc/nfc_cli.c diff --git a/applications/nfc/nfc_i.h b/applications/main/nfc/nfc_i.h similarity index 88% rename from applications/nfc/nfc_i.h rename to applications/main/nfc/nfc_i.h index c9ba7fff..15ea5348 100644 --- a/applications/nfc/nfc_i.h +++ b/applications/main/nfc/nfc_i.h @@ -33,8 +33,14 @@ #include #include +#include + #include "rpc/rpc_app.h" +#include + +ARRAY_DEF(MfClassicUserKeys, char*, M_PTR_OPLIST); + #define NFC_TEXT_STORE_SIZE 128 typedef enum { @@ -58,6 +64,7 @@ struct Nfc { char text_store[NFC_TEXT_STORE_SIZE + 1]; string_t text_box_store; uint8_t byte_input_store[6]; + MfClassicUserKeys_t mfc_key_strs; // Used in MFC key listing void* rpc_ctx; NfcRpcState rpc_state; @@ -98,7 +105,11 @@ void nfc_text_store_set(Nfc* nfc, const char* text, ...); void nfc_text_store_clear(Nfc* nfc); -void nfc_blink_start(Nfc* nfc); +void nfc_blink_read_start(Nfc* nfc); + +void nfc_blink_emulate_start(Nfc* nfc); + +void nfc_blink_detect_start(Nfc* nfc); void nfc_blink_stop(Nfc* nfc); diff --git a/applications/nfc/scenes/nfc_scene.c b/applications/main/nfc/scenes/nfc_scene.c similarity index 100% rename from applications/nfc/scenes/nfc_scene.c rename to applications/main/nfc/scenes/nfc_scene.c diff --git a/applications/nfc/scenes/nfc_scene.h b/applications/main/nfc/scenes/nfc_scene.h similarity index 100% rename from applications/nfc/scenes/nfc_scene.h rename to applications/main/nfc/scenes/nfc_scene.h diff --git a/applications/nfc/scenes/nfc_scene_config.h b/applications/main/nfc/scenes/nfc_scene_config.h similarity index 92% rename from applications/nfc/scenes/nfc_scene_config.h rename to applications/main/nfc/scenes/nfc_scene_config.h index 540fe109..a25850c8 100644 --- a/applications/nfc/scenes/nfc_scene_config.h +++ b/applications/main/nfc/scenes/nfc_scene_config.h @@ -32,6 +32,9 @@ ADD_SCENE(nfc, mf_classic_menu, MfClassicMenu) ADD_SCENE(nfc, mf_classic_emulate, MfClassicEmulate) ADD_SCENE(nfc, mf_classic_keys, MfClassicKeys) ADD_SCENE(nfc, mf_classic_keys_add, MfClassicKeysAdd) +ADD_SCENE(nfc, mf_classic_keys_list, MfClassicKeysList) +ADD_SCENE(nfc, mf_classic_keys_delete, MfClassicKeysDelete) +ADD_SCENE(nfc, mf_classic_keys_warn_duplicate, MfClassicKeysWarnDuplicate) ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack) ADD_SCENE(nfc, emv_read_success, EmvReadSuccess) ADD_SCENE(nfc, emv_menu, EmvMenu) diff --git a/applications/nfc/scenes/nfc_scene_debug.c b/applications/main/nfc/scenes/nfc_scene_debug.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_debug.c rename to applications/main/nfc/scenes/nfc_scene_debug.c diff --git a/applications/nfc/scenes/nfc_scene_delete.c b/applications/main/nfc/scenes/nfc_scene_delete.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_delete.c rename to applications/main/nfc/scenes/nfc_scene_delete.c diff --git a/applications/nfc/scenes/nfc_scene_delete_success.c b/applications/main/nfc/scenes/nfc_scene_delete_success.c similarity index 73% rename from applications/nfc/scenes/nfc_scene_delete_success.c rename to applications/main/nfc/scenes/nfc_scene_delete_success.c index 713b99eb..1664a9e5 100644 --- a/applications/nfc/scenes/nfc_scene_delete_success.c +++ b/applications/main/nfc/scenes/nfc_scene_delete_success.c @@ -25,8 +25,13 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventViewExit) { - consumed = scene_manager_search_and_switch_to_previous_scene( - nfc->scene_manager, NfcSceneFileSelect); + if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcSceneMfClassicKeys); + } else { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcSceneStart); + } } } return consumed; diff --git a/applications/nfc/scenes/nfc_scene_detect_reader.c b/applications/main/nfc/scenes/nfc_scene_detect_reader.c similarity index 98% rename from applications/nfc/scenes/nfc_scene_detect_reader.c rename to applications/main/nfc/scenes/nfc_scene_detect_reader.c index 8945feba..5f4582d8 100644 --- a/applications/nfc/scenes/nfc_scene_detect_reader.c +++ b/applications/main/nfc/scenes/nfc_scene_detect_reader.c @@ -29,7 +29,7 @@ void nfc_scene_detect_reader_on_enter(void* context) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDetectReader); - nfc_blink_start(nfc); + nfc_blink_read_start(nfc); } bool nfc_scene_detect_reader_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/nfc/scenes/nfc_scene_device_info.c b/applications/main/nfc/scenes/nfc_scene_device_info.c similarity index 95% rename from applications/nfc/scenes/nfc_scene_device_info.c rename to applications/main/nfc/scenes/nfc_scene_device_info.c index 8228c7ea..245aea5c 100644 --- a/applications/nfc/scenes/nfc_scene_device_info.c +++ b/applications/main/nfc/scenes/nfc_scene_device_info.c @@ -47,7 +47,9 @@ void nfc_scene_device_info_on_enter(void* context) { } string_clear(country_name); } - } else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) { + } else if( + dev_data->protocol == NfcDeviceProtocolMifareClassic || + dev_data->protocol == NfcDeviceProtocolMifareUl) { string_set(temp_str, nfc->dev->dev_data.parsed_data); } diff --git a/applications/nfc/scenes/nfc_scene_dict_not_found.c b/applications/main/nfc/scenes/nfc_scene_dict_not_found.c similarity index 85% rename from applications/nfc/scenes/nfc_scene_dict_not_found.c rename to applications/main/nfc/scenes/nfc_scene_dict_not_found.c index dc21b08b..781c5a93 100644 --- a/applications/nfc/scenes/nfc_scene_dict_not_found.c +++ b/applications/main/nfc/scenes/nfc_scene_dict_not_found.c @@ -31,7 +31,10 @@ bool nfc_scene_dict_not_found_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventViewExit) { - if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneExtraActions)) { + if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcSceneMfClassicKeys); + } else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneExtraActions)) { consumed = scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneExtraActions); } else { diff --git a/applications/nfc/scenes/nfc_scene_emulate_apdu_sequence.c b/applications/main/nfc/scenes/nfc_scene_emulate_apdu_sequence.c similarity index 96% rename from applications/nfc/scenes/nfc_scene_emulate_apdu_sequence.c rename to applications/main/nfc/scenes/nfc_scene_emulate_apdu_sequence.c index e6062ba4..358ad2ab 100644 --- a/applications/nfc/scenes/nfc_scene_emulate_apdu_sequence.c +++ b/applications/main/nfc/scenes/nfc_scene_emulate_apdu_sequence.c @@ -12,7 +12,7 @@ void nfc_scene_emulate_apdu_sequence_on_enter(void* context) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); nfc_worker_start(nfc->worker, NfcWorkerStateEmulateApdu, &nfc->dev->dev_data, NULL, nfc); - nfc_blink_start(nfc); + nfc_blink_emulate_start(nfc); } bool nfc_scene_emulate_apdu_sequence_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/nfc/scenes/nfc_scene_emulate_uid.c b/applications/main/nfc/scenes/nfc_scene_emulate_uid.c similarity index 99% rename from applications/nfc/scenes/nfc_scene_emulate_uid.c rename to applications/main/nfc/scenes/nfc_scene_emulate_uid.c index 0d92c9f0..f6402301 100644 --- a/applications/nfc/scenes/nfc_scene_emulate_uid.c +++ b/applications/main/nfc/scenes/nfc_scene_emulate_uid.c @@ -82,7 +82,7 @@ void nfc_scene_emulate_uid_on_enter(void* context) { nfc_emulate_uid_worker_callback, nfc); - nfc_blink_start(nfc); + nfc_blink_emulate_start(nfc); } bool nfc_scene_emulate_uid_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/nfc/scenes/nfc_scene_emv_menu.c b/applications/main/nfc/scenes/nfc_scene_emv_menu.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_emv_menu.c rename to applications/main/nfc/scenes/nfc_scene_emv_menu.c diff --git a/applications/nfc/scenes/nfc_scene_emv_read_success.c b/applications/main/nfc/scenes/nfc_scene_emv_read_success.c similarity index 95% rename from applications/nfc/scenes/nfc_scene_emv_read_success.c rename to applications/main/nfc/scenes/nfc_scene_emv_read_success.c index 9cf7ff9e..a40b4c1c 100644 --- a/applications/nfc/scenes/nfc_scene_emv_read_success.c +++ b/applications/main/nfc/scenes/nfc_scene_emv_read_success.c @@ -55,6 +55,8 @@ void nfc_scene_emv_read_success_on_enter(void* context) { string_clear(country_name); } + notification_message_block(nfc->notifications, &sequence_set_green_255); + widget_add_text_scroll_element(nfc->widget, 0, 0, 128, 52, string_get_cstr(temp_str)); string_clear(temp_str); @@ -83,6 +85,8 @@ bool nfc_scene_emv_read_success_on_event(void* context, SceneManagerEvent event) void nfc_scene_emv_read_success_on_exit(void* context) { Nfc* nfc = context; + notification_message_block(nfc->notifications, &sequence_reset_green); + // Clear view widget_reset(nfc->widget); } diff --git a/applications/nfc/scenes/nfc_scene_exit_confirm.c b/applications/main/nfc/scenes/nfc_scene_exit_confirm.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_exit_confirm.c rename to applications/main/nfc/scenes/nfc_scene_exit_confirm.c diff --git a/applications/nfc/scenes/nfc_scene_extra_actions.c b/applications/main/nfc/scenes/nfc_scene_extra_actions.c similarity index 98% rename from applications/nfc/scenes/nfc_scene_extra_actions.c rename to applications/main/nfc/scenes/nfc_scene_extra_actions.c index 43e49e5a..e888e9d3 100644 --- a/applications/nfc/scenes/nfc_scene_extra_actions.c +++ b/applications/main/nfc/scenes/nfc_scene_extra_actions.c @@ -17,7 +17,7 @@ void nfc_scene_extra_actions_on_enter(void* context) { submenu_add_item( submenu, - "Mf Classic Keys", + "Mifare Classic Keys", SubmenuIndexMfClassicKeys, nfc_scene_extra_actions_submenu_callback, nfc); diff --git a/applications/nfc/scenes/nfc_scene_field.c b/applications/main/nfc/scenes/nfc_scene_field.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_field.c rename to applications/main/nfc/scenes/nfc_scene_field.c diff --git a/applications/nfc/scenes/nfc_scene_file_select.c b/applications/main/nfc/scenes/nfc_scene_file_select.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_file_select.c rename to applications/main/nfc/scenes/nfc_scene_file_select.c diff --git a/applications/nfc/scenes/nfc_scene_generate_info.c b/applications/main/nfc/scenes/nfc_scene_generate_info.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_generate_info.c rename to applications/main/nfc/scenes/nfc_scene_generate_info.c diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_dict_attack.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c similarity index 99% rename from applications/nfc/scenes/nfc_scene_mf_classic_dict_attack.c rename to applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c index d821c182..b23f4b8f 100644 --- a/applications/nfc/scenes/nfc_scene_mf_classic_dict_attack.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c @@ -90,7 +90,7 @@ void nfc_scene_mf_classic_dict_attack_on_enter(void* context) { Nfc* nfc = context; nfc_scene_mf_classic_dict_attack_prepare_view(nfc, DictAttackStateIdle); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDictAttack); - nfc_blink_start(nfc); + nfc_blink_read_start(nfc); } bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_emulate.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c similarity index 98% rename from applications/nfc/scenes/nfc_scene_mf_classic_emulate.c rename to applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c index 044388b8..65639b2b 100644 --- a/applications/nfc/scenes/nfc_scene_mf_classic_emulate.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c @@ -35,7 +35,7 @@ void nfc_scene_mf_classic_emulate_on_enter(void* context) { &nfc->dev->dev_data, nfc_mf_classic_emulate_worker_callback, nfc); - nfc_blink_start(nfc); + nfc_blink_emulate_start(nfc); } bool nfc_scene_mf_classic_emulate_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_keys.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c similarity index 66% rename from applications/nfc/scenes/nfc_scene_mf_classic_keys.c rename to applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c index fcb8bc18..a2e6ae74 100644 --- a/applications/nfc/scenes/nfc_scene_mf_classic_keys.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c @@ -26,15 +26,25 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) { } widget_add_string_element( - nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "MF Classic Keys"); + nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Mifare Classic Keys"); char temp_str[32]; - snprintf(temp_str, sizeof(temp_str), "Flipper dict: %ld", flipper_dict_keys_total); + snprintf(temp_str, sizeof(temp_str), "Flipper list: %ld", flipper_dict_keys_total); widget_add_string_element(nfc->widget, 0, 20, AlignLeft, AlignTop, FontSecondary, temp_str); - snprintf(temp_str, sizeof(temp_str), "User dict: %ld", user_dict_keys_total); + snprintf(temp_str, sizeof(temp_str), "User list: %ld", user_dict_keys_total); widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str); widget_add_button_element( nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc); - widget_add_icon_element(nfc->widget, 90, 12, &I_Keychain); + widget_add_button_element( + nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_mf_classic_keys_widget_callback, nfc); + widget_add_icon_element(nfc->widget, 87, 13, &I_Keychain_39x36); + if(user_dict_keys_total > 0) { + widget_add_button_element( + nfc->widget, + GuiButtonTypeRight, + "List", + nfc_scene_mf_classic_keys_widget_callback, + nfc); + } view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } @@ -47,6 +57,12 @@ bool nfc_scene_mf_classic_keys_on_event(void* context, SceneManagerEvent event) if(event.event == GuiButtonTypeCenter) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysAdd); consumed = true; + } else if(event.event == GuiButtonTypeLeft) { + scene_manager_previous_scene(nfc->scene_manager); + consumed = true; + } else if(event.event == GuiButtonTypeRight) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysList); + consumed = true; } } diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_keys_add.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_add.c similarity index 76% rename from applications/nfc/scenes/nfc_scene_mf_classic_keys_add.c rename to applications/main/nfc/scenes/nfc_scene_mf_classic_keys_add.c index 9f56b0f4..2921d21c 100644 --- a/applications/nfc/scenes/nfc_scene_mf_classic_keys_add.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_add.c @@ -29,15 +29,16 @@ bool nfc_scene_mf_classic_keys_add_on_event(void* context, SceneManagerEvent eve if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventByteInputDone) { // Add key to dict - bool key_added = false; MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser); if(dict) { - if(mf_classic_dict_add_key(dict, nfc->byte_input_store)) { - key_added = true; + if(mf_classic_dict_is_key_present(dict, nfc->byte_input_store)) { + scene_manager_next_scene( + nfc->scene_manager, NfcSceneMfClassicKeysWarnDuplicate); + } else if(mf_classic_dict_add_key(dict, nfc->byte_input_store)) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess); + } else { + scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound); } - } - if(key_added) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess); } else { scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound); } diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_delete.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_delete.c new file mode 100644 index 00000000..16a189da --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_delete.c @@ -0,0 +1,77 @@ +#include "../nfc_i.h" + +void nfc_scene_mf_classic_keys_delete_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + Nfc* nfc = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_scene_mf_classic_keys_delete_on_enter(void* context) { + Nfc* nfc = context; + MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser); + uint32_t key_index = + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicKeysDelete); + // Setup Custom Widget view + string_t key_str; + string_init(key_str); + + widget_add_string_element( + nfc->widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "Delete this key?"); + widget_add_button_element( + nfc->widget, + GuiButtonTypeLeft, + "Cancel", + nfc_scene_mf_classic_keys_delete_widget_callback, + nfc); + widget_add_button_element( + nfc->widget, + GuiButtonTypeRight, + "Delete", + nfc_scene_mf_classic_keys_delete_widget_callback, + nfc); + + mf_classic_dict_get_key_at_index_str(dict, key_str, key_index); + widget_add_string_element( + nfc->widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(key_str)); + + string_clear(key_str); + mf_classic_dict_free(dict); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); +} + +bool nfc_scene_mf_classic_keys_delete_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + uint32_t key_index = + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicKeysDelete); + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeLeft) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcSceneMfClassicKeys); + } else if(event.event == GuiButtonTypeRight) { + MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser); + if(mf_classic_dict_delete_index(dict, key_index)) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess); + } else { + scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcSceneMfClassicKeys); + } + mf_classic_dict_free(dict); + consumed = true; + } + } + + return consumed; +} + +void nfc_scene_mf_classic_keys_delete_on_exit(void* context) { + Nfc* nfc = context; + + widget_reset(nfc->widget); +} diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c new file mode 100644 index 00000000..6670ae13 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c @@ -0,0 +1,100 @@ +#include "../nfc_i.h" + +#define NFC_SCENE_MF_CLASSIC_KEYS_LIST_MAX (100) + +void nfc_scene_mf_classic_keys_list_submenu_callback(void* context, uint32_t index) { + furi_assert(context); + + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_mf_classic_keys_list_popup_callback(void* context) { + furi_assert(context); + + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); +} + +void nfc_scene_mf_classic_keys_list_prepare(Nfc* nfc, MfClassicDict* dict) { + Submenu* submenu = nfc->submenu; + uint32_t index = 0; + string_t temp_key; + string_init(temp_key); + + submenu_set_header(submenu, "Select key to delete:"); + while(mf_classic_dict_get_next_key_str(dict, temp_key)) { + char* current_key = (char*)malloc(sizeof(char) * 13); + strncpy(current_key, string_get_cstr(temp_key), 12); + MfClassicUserKeys_push_back(nfc->mfc_key_strs, current_key); + FURI_LOG_D("ListKeys", "Key %d: %s", index, current_key); + submenu_add_item( + submenu, current_key, index++, nfc_scene_mf_classic_keys_list_submenu_callback, nfc); + } + string_clear(temp_key); +} + +void nfc_scene_mf_classic_keys_list_on_enter(void* context) { + Nfc* nfc = context; + MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser); + MfClassicUserKeys_init(nfc->mfc_key_strs); + if(dict) { + uint32_t total_user_keys = mf_classic_dict_get_total_keys(dict); + if(total_user_keys < NFC_SCENE_MF_CLASSIC_KEYS_LIST_MAX) { + nfc_scene_mf_classic_keys_list_prepare(nfc, dict); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); + } else { + popup_set_header(nfc->popup, "Too many keys!", 64, 0, AlignCenter, AlignTop); + popup_set_text( + nfc->popup, + "Edit user dictionary\nwith file browser", + 64, + 12, + AlignCenter, + AlignTop); + popup_set_callback(nfc->popup, nfc_scene_mf_classic_keys_list_popup_callback); + popup_set_context(nfc->popup, nfc); + popup_set_timeout(nfc->popup, 3000); + popup_enable_timeout(nfc->popup); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); + } + mf_classic_dict_free(dict); + } else { + popup_set_header( + nfc->popup, "Failed to load dictionary", 64, 32, AlignCenter, AlignCenter); + popup_set_callback(nfc->popup, nfc_scene_mf_classic_keys_list_popup_callback); + popup_set_context(nfc->popup, nfc); + popup_set_timeout(nfc->popup, 3000); + popup_enable_timeout(nfc->popup); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); + } +} + +bool nfc_scene_mf_classic_keys_list_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventViewExit) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } else { + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneMfClassicKeysDelete, event.event); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysDelete); + consumed = true; + } + } + return consumed; +} + +void nfc_scene_mf_classic_keys_list_on_exit(void* context) { + Nfc* nfc = context; + + MfClassicUserKeys_it_t it; + for(MfClassicUserKeys_it(it, nfc->mfc_key_strs); !MfClassicUserKeys_end_p(it); + MfClassicUserKeys_next(it)) { + free(*MfClassicUserKeys_ref(it)); + } + MfClassicUserKeys_clear(nfc->mfc_key_strs); + submenu_reset(nfc->submenu); + popup_reset(nfc->popup); +} diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_warn_duplicate.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_warn_duplicate.c new file mode 100644 index 00000000..ab41989b --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_warn_duplicate.c @@ -0,0 +1,47 @@ +#include "../nfc_i.h" + +void nfc_scene_mf_classic_keys_warn_duplicate_popup_callback(void* context) { + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); +} + +void nfc_scene_mf_classic_keys_warn_duplicate_on_enter(void* context) { + Nfc* nfc = context; + + // Setup view + Popup* popup = nfc->popup; + popup_set_icon(popup, 72, 16, &I_DolphinCommon_56x48); + popup_set_header(popup, "Key already exists!", 64, 3, AlignCenter, AlignTop); + popup_set_text( + popup, + "Please enter a\n" + "different key.", + 4, + 24, + AlignLeft, + AlignTop); + popup_set_timeout(popup, 5000); + popup_set_context(popup, nfc); + popup_set_callback(popup, nfc_scene_mf_classic_keys_warn_duplicate_popup_callback); + popup_enable_timeout(popup); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); +} + +bool nfc_scene_mf_classic_keys_warn_duplicate_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventViewExit) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcSceneMfClassicKeysAdd); + } + } + return consumed; +} + +void nfc_scene_mf_classic_keys_warn_duplicate_on_exit(void* context) { + Nfc* nfc = context; + + popup_reset(nfc->popup); +} diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_menu.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_menu.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_mf_classic_menu.c rename to applications/main/nfc/scenes/nfc_scene_mf_classic_menu.c diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_read_success.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_read_success.c similarity index 94% rename from applications/nfc/scenes/nfc_scene_mf_classic_read_success.c rename to applications/main/nfc/scenes/nfc_scene_mf_classic_read_success.c index efe67670..3ca24416 100644 --- a/applications/nfc/scenes/nfc_scene_mf_classic_read_success.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_read_success.c @@ -48,6 +48,8 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) { widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); string_clear(temp_str); + notification_message_block(nfc->notifications, &sequence_set_green_255); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } @@ -76,6 +78,8 @@ bool nfc_scene_mf_classic_read_success_on_event(void* context, SceneManagerEvent void nfc_scene_mf_classic_read_success_on_exit(void* context) { Nfc* nfc = context; + notification_message_block(nfc->notifications, &sequence_reset_green); + // Clear view widget_reset(nfc->widget); } diff --git a/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c b/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c new file mode 100644 index 00000000..dd842464 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c @@ -0,0 +1,125 @@ +#include "../nfc_i.h" + +#define TAG "NfcSceneMfDesfireApp" + +enum SubmenuIndex { + SubmenuIndexAppInfo, + SubmenuIndexDynamic, // dynamic indexes start here +}; + +void nfc_scene_mf_desfire_popup_callback(void* context) { + furi_assert(context); + + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); +} + +MifareDesfireApplication* nfc_scene_mf_desfire_app_get_app(Nfc* nfc) { + uint32_t app_idx = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp) >> + 1; + MifareDesfireApplication* app = nfc->dev->dev_data.mf_df_data.app_head; + for(uint32_t i = 0; i < app_idx && app; i++) { + app = app->next; + } + return app; +} + +void nfc_scene_mf_desfire_app_submenu_callback(void* context, uint32_t index) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_mf_desfire_app_on_enter(void* context) { + Nfc* nfc = context; + MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc); + if(!app) { + popup_set_icon(nfc->popup, 5, 5, &I_WarningDolphin_45x42); + popup_set_header(nfc->popup, "Empty card!", 55, 12, AlignLeft, AlignBottom); + popup_set_callback(nfc->popup, nfc_scene_mf_desfire_popup_callback); + popup_set_context(nfc->popup, nfc); + popup_set_timeout(nfc->popup, 3000); + popup_enable_timeout(nfc->popup); + popup_set_text(nfc->popup, "No application\nfound.", 55, 15, AlignLeft, AlignTop); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); + } else { + text_box_set_font(nfc->text_box, TextBoxFontHex); + submenu_add_item( + nfc->submenu, + "App info", + SubmenuIndexAppInfo, + nfc_scene_mf_desfire_app_submenu_callback, + nfc); + + uint16_t cap = NFC_TEXT_STORE_SIZE; + char* buf = nfc->text_store; + int idx = SubmenuIndexDynamic; + for(MifareDesfireFile* file = app->file_head; file; file = file->next) { + int size = snprintf(buf, cap, "File %d", file->id); + if(size < 0 || size >= cap) { + FURI_LOG_W( + TAG, + "Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated"); + break; + } + char* label = buf; + cap -= size + 1; + buf += size + 1; + submenu_add_item( + nfc->submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc); + } + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); + } +} + +bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp); + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventViewExit) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } else { + MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc); + TextBox* text_box = nfc->text_box; + string_reset(nfc->text_box_store); + if(event.event == SubmenuIndexAppInfo) { + mf_df_cat_application_info(app, nfc->text_box_store); + } else { + uint16_t index = event.event - SubmenuIndexDynamic; + MifareDesfireFile* file = app->file_head; + for(int i = 0; file && i < index; i++) { + file = file->next; + } + if(!file) { + return false; + } + mf_df_cat_file(file, nfc->text_box_store); + } + text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state | 1); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + if(state & 1) { + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state & ~1); + consumed = true; + } + } + + return consumed; +} + +void nfc_scene_mf_desfire_app_on_exit(void* context) { + Nfc* nfc = context; + + // Clear views + popup_reset(nfc->popup); + text_box_reset(nfc->text_box); + string_reset(nfc->text_box_store); + submenu_reset(nfc->submenu); +} diff --git a/applications/nfc/scenes/nfc_scene_mf_desfire_data.c b/applications/main/nfc/scenes/nfc_scene_mf_desfire_data.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_mf_desfire_data.c rename to applications/main/nfc/scenes/nfc_scene_mf_desfire_data.c diff --git a/applications/nfc/scenes/nfc_scene_mf_desfire_menu.c b/applications/main/nfc/scenes/nfc_scene_mf_desfire_menu.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_mf_desfire_menu.c rename to applications/main/nfc/scenes/nfc_scene_mf_desfire_menu.c diff --git a/applications/nfc/scenes/nfc_scene_mf_desfire_read_success.c b/applications/main/nfc/scenes/nfc_scene_mf_desfire_read_success.c similarity index 95% rename from applications/nfc/scenes/nfc_scene_mf_desfire_read_success.c rename to applications/main/nfc/scenes/nfc_scene_mf_desfire_read_success.c index 4827c285..12047c15 100644 --- a/applications/nfc/scenes/nfc_scene_mf_desfire_read_success.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_desfire_read_success.c @@ -52,6 +52,8 @@ void nfc_scene_mf_desfire_read_success_on_enter(void* context) { string_push_back(temp_str, 's'); } + notification_message_block(nfc->notifications, &sequence_set_green_255); + // Add text scroll element widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); string_clear(temp_str); @@ -88,6 +90,8 @@ bool nfc_scene_mf_desfire_read_success_on_event(void* context, SceneManagerEvent void nfc_scene_mf_desfire_read_success_on_exit(void* context) { Nfc* nfc = context; + notification_message_block(nfc->notifications, &sequence_reset_green); + // Clean dialog widget_reset(nfc->widget); } diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_data.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_data.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_mf_ultralight_data.c rename to applications/main/nfc/scenes/nfc_scene_mf_ultralight_data.c diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_emulate.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c similarity index 98% rename from applications/nfc/scenes/nfc_scene_mf_ultralight_emulate.c rename to applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c index ce375554..712ddc07 100644 --- a/applications/nfc/scenes/nfc_scene_mf_ultralight_emulate.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c @@ -35,7 +35,7 @@ void nfc_scene_mf_ultralight_emulate_on_enter(void* context) { &nfc->dev->dev_data, nfc_mf_ultralight_emulate_worker_callback, nfc); - nfc_blink_start(nfc); + nfc_blink_emulate_start(nfc); } bool nfc_scene_mf_ultralight_emulate_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_key_input.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_key_input.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_mf_ultralight_key_input.c rename to applications/main/nfc/scenes/nfc_scene_mf_ultralight_key_input.c diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_menu.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_mf_ultralight_menu.c rename to applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c similarity index 97% rename from applications/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c rename to applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c index 853ccb05..25008004 100644 --- a/applications/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c @@ -27,7 +27,7 @@ void nfc_scene_mf_ultralight_read_auth_set_state(Nfc* nfc, NfcSceneMfUlReadState popup_reset(nfc->popup); popup_set_text( nfc->popup, "Apply card to\nFlipper's back", 97, 24, AlignCenter, AlignTop); - popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual); + popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50); } else if(state == NfcSceneMfUlReadStateReading) { popup_reset(nfc->popup); popup_set_header( @@ -65,7 +65,7 @@ void nfc_scene_mf_ultralight_read_auth_on_enter(void* context) { nfc_scene_mf_ultralight_read_auth_worker_callback, nfc); - nfc_blink_start(nfc); + nfc_blink_read_start(nfc); } bool nfc_scene_mf_ultralight_read_auth_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_read_auth_result.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth_result.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_mf_ultralight_read_auth_result.c rename to applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth_result.c diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_success.c similarity index 71% rename from applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c rename to applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_success.c index d775bb71..f6dc5984 100644 --- a/applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_success.c @@ -34,19 +34,25 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) { nfc); string_t temp_str; - string_init_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(mf_ul_data->type, true)); - string_cat_printf(temp_str, "UID:"); - for(size_t i = 0; i < data->uid_len; i++) { - string_cat_printf(temp_str, " %02X", data->uid[i]); - } - string_cat_printf( - temp_str, "\nPages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4); - if(mf_ul_data->data_read != mf_ul_data->data_size) { - string_cat_printf(temp_str, "\nPassword-protected pages!"); + if(string_size(nfc->dev->dev_data.parsed_data)) { + string_init_set(temp_str, nfc->dev->dev_data.parsed_data); + } else { + string_init_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(mf_ul_data->type, true)); + string_cat_printf(temp_str, "UID:"); + for(size_t i = 0; i < data->uid_len; i++) { + string_cat_printf(temp_str, " %02X", data->uid[i]); + } + string_cat_printf( + temp_str, "\nPages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4); + if(mf_ul_data->data_read != mf_ul_data->data_size) { + string_cat_printf(temp_str, "\nPassword-protected pages!"); + } } widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); string_clear(temp_str); + notification_message_block(nfc->notifications, &sequence_set_green_255); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } @@ -73,6 +79,8 @@ bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEv void nfc_scene_mf_ultralight_read_success_on_exit(void* context) { Nfc* nfc = context; + notification_message_block(nfc->notifications, &sequence_reset_green); + // Clean view widget_reset(nfc->widget); } diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_unlock_menu.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_unlock_menu.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_mf_ultralight_unlock_menu.c rename to applications/main/nfc/scenes/nfc_scene_mf_ultralight_unlock_menu.c diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_unlock_warn.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_unlock_warn.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_mf_ultralight_unlock_warn.c rename to applications/main/nfc/scenes/nfc_scene_mf_ultralight_unlock_warn.c diff --git a/applications/nfc/scenes/nfc_scene_mfkey_complete.c b/applications/main/nfc/scenes/nfc_scene_mfkey_complete.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_mfkey_complete.c rename to applications/main/nfc/scenes/nfc_scene_mfkey_complete.c diff --git a/applications/nfc/scenes/nfc_scene_mfkey_nonces_info.c b/applications/main/nfc/scenes/nfc_scene_mfkey_nonces_info.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_mfkey_nonces_info.c rename to applications/main/nfc/scenes/nfc_scene_mfkey_nonces_info.c diff --git a/applications/nfc/scenes/nfc_scene_nfc_data_info.c b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_nfc_data_info.c rename to applications/main/nfc/scenes/nfc_scene_nfc_data_info.c diff --git a/applications/nfc/scenes/nfc_scene_nfca_menu.c b/applications/main/nfc/scenes/nfc_scene_nfca_menu.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_nfca_menu.c rename to applications/main/nfc/scenes/nfc_scene_nfca_menu.c diff --git a/applications/nfc/scenes/nfc_scene_nfca_read_success.c b/applications/main/nfc/scenes/nfc_scene_nfca_read_success.c similarity index 93% rename from applications/nfc/scenes/nfc_scene_nfca_read_success.c rename to applications/main/nfc/scenes/nfc_scene_nfca_read_success.c index 3467a03b..c695da24 100644 --- a/applications/nfc/scenes/nfc_scene_nfca_read_success.c +++ b/applications/main/nfc/scenes/nfc_scene_nfca_read_success.c @@ -25,6 +25,8 @@ void nfc_scene_nfca_read_success_on_enter(void* context) { string_t temp_str; string_init_set_str(temp_str, "\e#Unknown ISO tag\n"); + notification_message_block(nfc->notifications, &sequence_set_green_255); + char iso_type = FURI_BIT(data->sak, 5) ? '4' : '3'; string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type); string_cat_printf(temp_str, "UID:"); @@ -67,6 +69,8 @@ bool nfc_scene_nfca_read_success_on_event(void* context, SceneManagerEvent event void nfc_scene_nfca_read_success_on_exit(void* context) { Nfc* nfc = context; + notification_message_block(nfc->notifications, &sequence_reset_green); + // Clear view widget_reset(nfc->widget); } diff --git a/applications/nfc/scenes/nfc_scene_read.c b/applications/main/nfc/scenes/nfc_scene_read.c similarity index 96% rename from applications/nfc/scenes/nfc_scene_read.c rename to applications/main/nfc/scenes/nfc_scene_read.c index 00b7c8fa..e6df476f 100644 --- a/applications/nfc/scenes/nfc_scene_read.c +++ b/applications/main/nfc/scenes/nfc_scene_read.c @@ -26,7 +26,7 @@ void nfc_scene_read_set_state(Nfc* nfc, NfcSceneReadState state) { popup_reset(nfc->popup); popup_set_text( nfc->popup, "Apply card to\nFlipper's back", 97, 24, AlignCenter, AlignTop); - popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual); + popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50); } else if(state == NfcSceneReadStateReading) { popup_reset(nfc->popup); popup_set_header( @@ -49,7 +49,7 @@ void nfc_scene_read_on_enter(void* context) { nfc_worker_start( nfc->worker, NfcWorkerStateRead, &nfc->dev->dev_data, nfc_scene_read_worker_callback, nfc); - nfc_blink_start(nfc); + nfc_blink_read_start(nfc); } bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) { @@ -92,9 +92,11 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) { consumed = true; } else if(event.event == NfcWorkerEventCardDetected) { nfc_scene_read_set_state(nfc, NfcSceneReadStateReading); + nfc_blink_detect_start(nfc); consumed = true; } else if(event.event == NfcWorkerEventNoCardDetected) { nfc_scene_read_set_state(nfc, NfcSceneReadStateDetecting); + nfc_blink_read_start(nfc); consumed = true; } } diff --git a/applications/nfc/scenes/nfc_scene_read_card_success.c b/applications/main/nfc/scenes/nfc_scene_read_card_success.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_read_card_success.c rename to applications/main/nfc/scenes/nfc_scene_read_card_success.c diff --git a/applications/nfc/scenes/nfc_scene_restore_original.c b/applications/main/nfc/scenes/nfc_scene_restore_original.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_restore_original.c rename to applications/main/nfc/scenes/nfc_scene_restore_original.c diff --git a/applications/nfc/scenes/nfc_scene_restore_original_confirm.c b/applications/main/nfc/scenes/nfc_scene_restore_original_confirm.c similarity index 96% rename from applications/nfc/scenes/nfc_scene_restore_original_confirm.c rename to applications/main/nfc/scenes/nfc_scene_restore_original_confirm.c index 2c12749d..730dd41e 100644 --- a/applications/nfc/scenes/nfc_scene_restore_original_confirm.c +++ b/applications/main/nfc/scenes/nfc_scene_restore_original_confirm.c @@ -11,7 +11,7 @@ void nfc_scene_restore_original_confirm_on_enter(void* context) { DialogEx* dialog_ex = nfc->dialog_ex; dialog_ex_set_header(dialog_ex, "Restore Card Data?", 64, 0, AlignCenter, AlignTop); - dialog_ex_set_icon(dialog_ex, 5, 15, &I_Restoring); + dialog_ex_set_icon(dialog_ex, 5, 15, &I_Restoring_38x32); dialog_ex_set_text( dialog_ex, "It will be returned\nto its original state.", 47, 21, AlignLeft, AlignTop); dialog_ex_set_left_button_text(dialog_ex, "Cancel"); diff --git a/applications/nfc/scenes/nfc_scene_retry_confirm.c b/applications/main/nfc/scenes/nfc_scene_retry_confirm.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_retry_confirm.c rename to applications/main/nfc/scenes/nfc_scene_retry_confirm.c diff --git a/applications/nfc/scenes/nfc_scene_rpc.c b/applications/main/nfc/scenes/nfc_scene_rpc.c similarity index 98% rename from applications/nfc/scenes/nfc_scene_rpc.c rename to applications/main/nfc/scenes/nfc_scene_rpc.c index 7a9eb450..e5128a52 100644 --- a/applications/nfc/scenes/nfc_scene_rpc.c +++ b/applications/main/nfc/scenes/nfc_scene_rpc.c @@ -62,7 +62,7 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) { nfc->rpc_state = NfcRpcStateEmulating; result = true; - nfc_blink_start(nfc); + nfc_blink_emulate_start(nfc); nfc_text_store_set(nfc, "emulating\n%s", nfc->dev->dev_name); popup_set_text(popup, nfc->text_store, 89, 44, AlignCenter, AlignTop); } diff --git a/applications/nfc/scenes/nfc_scene_save_name.c b/applications/main/nfc/scenes/nfc_scene_save_name.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_save_name.c rename to applications/main/nfc/scenes/nfc_scene_save_name.c diff --git a/applications/nfc/scenes/nfc_scene_save_success.c b/applications/main/nfc/scenes/nfc_scene_save_success.c similarity index 85% rename from applications/nfc/scenes/nfc_scene_save_success.c rename to applications/main/nfc/scenes/nfc_scene_save_success.c index a3b17451..dcd2519f 100644 --- a/applications/nfc/scenes/nfc_scene_save_success.c +++ b/applications/main/nfc/scenes/nfc_scene_save_success.c @@ -27,7 +27,10 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventViewExit) { - if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) { + if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcSceneMfClassicKeys); + } else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) { consumed = scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneSavedMenu); } else { diff --git a/applications/nfc/scenes/nfc_scene_saved_menu.c b/applications/main/nfc/scenes/nfc_scene_saved_menu.c similarity index 96% rename from applications/nfc/scenes/nfc_scene_saved_menu.c rename to applications/main/nfc/scenes/nfc_scene_saved_menu.c index c7aec5d8..c1043b3a 100644 --- a/applications/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_saved_menu.c @@ -91,7 +91,9 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { bool application_info_present = false; if(dev_data->protocol == NfcDeviceProtocolEMV) { application_info_present = true; - } else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) { + } else if( + dev_data->protocol == NfcDeviceProtocolMifareClassic || + dev_data->protocol == NfcDeviceProtocolMifareUl) { application_info_present = nfc_supported_card_verify_and_parse(dev_data); } diff --git a/applications/nfc/scenes/nfc_scene_set_atqa.c b/applications/main/nfc/scenes/nfc_scene_set_atqa.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_set_atqa.c rename to applications/main/nfc/scenes/nfc_scene_set_atqa.c diff --git a/applications/nfc/scenes/nfc_scene_set_sak.c b/applications/main/nfc/scenes/nfc_scene_set_sak.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_set_sak.c rename to applications/main/nfc/scenes/nfc_scene_set_sak.c diff --git a/applications/nfc/scenes/nfc_scene_set_type.c b/applications/main/nfc/scenes/nfc_scene_set_type.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_set_type.c rename to applications/main/nfc/scenes/nfc_scene_set_type.c diff --git a/applications/nfc/scenes/nfc_scene_set_uid.c b/applications/main/nfc/scenes/nfc_scene_set_uid.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_set_uid.c rename to applications/main/nfc/scenes/nfc_scene_set_uid.c diff --git a/applications/nfc/scenes/nfc_scene_start.c b/applications/main/nfc/scenes/nfc_scene_start.c similarity index 100% rename from applications/nfc/scenes/nfc_scene_start.c rename to applications/main/nfc/scenes/nfc_scene_start.c diff --git a/applications/nfc/views/detect_reader.c b/applications/main/nfc/views/detect_reader.c similarity index 100% rename from applications/nfc/views/detect_reader.c rename to applications/main/nfc/views/detect_reader.c diff --git a/applications/nfc/views/detect_reader.h b/applications/main/nfc/views/detect_reader.h similarity index 100% rename from applications/nfc/views/detect_reader.h rename to applications/main/nfc/views/detect_reader.h diff --git a/applications/nfc/views/dict_attack.c b/applications/main/nfc/views/dict_attack.c similarity index 100% rename from applications/nfc/views/dict_attack.c rename to applications/main/nfc/views/dict_attack.c diff --git a/applications/nfc/views/dict_attack.h b/applications/main/nfc/views/dict_attack.h similarity index 100% rename from applications/nfc/views/dict_attack.h rename to applications/main/nfc/views/dict_attack.h diff --git a/applications/subghz/application.fam b/applications/main/subghz/application.fam similarity index 100% rename from applications/subghz/application.fam rename to applications/main/subghz/application.fam diff --git a/applications/subghz/helpers/subghz_chat.c b/applications/main/subghz/helpers/subghz_chat.c similarity index 100% rename from applications/subghz/helpers/subghz_chat.c rename to applications/main/subghz/helpers/subghz_chat.c diff --git a/applications/subghz/helpers/subghz_chat.h b/applications/main/subghz/helpers/subghz_chat.h similarity index 100% rename from applications/subghz/helpers/subghz_chat.h rename to applications/main/subghz/helpers/subghz_chat.h diff --git a/applications/subghz/helpers/subghz_custom_event.h b/applications/main/subghz/helpers/subghz_custom_event.h similarity index 100% rename from applications/subghz/helpers/subghz_custom_event.h rename to applications/main/subghz/helpers/subghz_custom_event.h diff --git a/applications/subghz/helpers/subghz_frequency_analyzer_worker.c b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c similarity index 100% rename from applications/subghz/helpers/subghz_frequency_analyzer_worker.c rename to applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c diff --git a/applications/subghz/helpers/subghz_frequency_analyzer_worker.h b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.h similarity index 100% rename from applications/subghz/helpers/subghz_frequency_analyzer_worker.h rename to applications/main/subghz/helpers/subghz_frequency_analyzer_worker.h diff --git a/applications/subghz/helpers/subghz_testing.c b/applications/main/subghz/helpers/subghz_testing.c similarity index 100% rename from applications/subghz/helpers/subghz_testing.c rename to applications/main/subghz/helpers/subghz_testing.c diff --git a/applications/subghz/helpers/subghz_testing.h b/applications/main/subghz/helpers/subghz_testing.h similarity index 100% rename from applications/subghz/helpers/subghz_testing.h rename to applications/main/subghz/helpers/subghz_testing.h diff --git a/applications/subghz/helpers/subghz_types.h b/applications/main/subghz/helpers/subghz_types.h similarity index 98% rename from applications/subghz/helpers/subghz_types.h rename to applications/main/subghz/helpers/subghz_types.h index 8da4c8f5..7fe1e7ce 100644 --- a/applications/subghz/helpers/subghz_types.h +++ b/applications/main/subghz/helpers/subghz_types.h @@ -47,7 +47,6 @@ typedef enum { SubGhzLoadKeyStateUnknown, SubGhzLoadKeyStateOK, SubGhzLoadKeyStateParseErr, - SubGhzLoadKeyStateOnlyRx, } SubGhzLoadKeyState; /** SubGhzLock */ diff --git a/applications/subghz/scenes/subghz_scene.c b/applications/main/subghz/scenes/subghz_scene.c similarity index 100% rename from applications/subghz/scenes/subghz_scene.c rename to applications/main/subghz/scenes/subghz_scene.c diff --git a/applications/subghz/scenes/subghz_scene.h b/applications/main/subghz/scenes/subghz_scene.h similarity index 100% rename from applications/subghz/scenes/subghz_scene.h rename to applications/main/subghz/scenes/subghz_scene.h diff --git a/applications/subghz/scenes/subghz_scene_config.h b/applications/main/subghz/scenes/subghz_scene_config.h similarity index 100% rename from applications/subghz/scenes/subghz_scene_config.h rename to applications/main/subghz/scenes/subghz_scene_config.h diff --git a/applications/subghz/scenes/subghz_scene_delete.c b/applications/main/subghz/scenes/subghz_scene_delete.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_delete.c rename to applications/main/subghz/scenes/subghz_scene_delete.c diff --git a/applications/subghz/scenes/subghz_scene_delete_raw.c b/applications/main/subghz/scenes/subghz_scene_delete_raw.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_delete_raw.c rename to applications/main/subghz/scenes/subghz_scene_delete_raw.c diff --git a/applications/subghz/scenes/subghz_scene_delete_success.c b/applications/main/subghz/scenes/subghz_scene_delete_success.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_delete_success.c rename to applications/main/subghz/scenes/subghz_scene_delete_success.c diff --git a/applications/subghz/scenes/subghz_scene_frequency_analyzer.c b/applications/main/subghz/scenes/subghz_scene_frequency_analyzer.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_frequency_analyzer.c rename to applications/main/subghz/scenes/subghz_scene_frequency_analyzer.c diff --git a/applications/subghz/scenes/subghz_scene_more_raw.c b/applications/main/subghz/scenes/subghz_scene_more_raw.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_more_raw.c rename to applications/main/subghz/scenes/subghz_scene_more_raw.c diff --git a/applications/subghz/scenes/subghz_scene_need_saving.c b/applications/main/subghz/scenes/subghz_scene_need_saving.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_need_saving.c rename to applications/main/subghz/scenes/subghz_scene_need_saving.c diff --git a/applications/subghz/scenes/subghz_scene_read_raw.c b/applications/main/subghz/scenes/subghz_scene_read_raw.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_read_raw.c rename to applications/main/subghz/scenes/subghz_scene_read_raw.c diff --git a/applications/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_receiver.c rename to applications/main/subghz/scenes/subghz_scene_receiver.c diff --git a/applications/subghz/scenes/subghz_scene_receiver_config.c b/applications/main/subghz/scenes/subghz_scene_receiver_config.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_receiver_config.c rename to applications/main/subghz/scenes/subghz_scene_receiver_config.c diff --git a/applications/subghz/scenes/subghz_scene_receiver_info.c b/applications/main/subghz/scenes/subghz_scene_receiver_info.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_receiver_info.c rename to applications/main/subghz/scenes/subghz_scene_receiver_info.c diff --git a/applications/subghz/scenes/subghz_scene_rpc.c b/applications/main/subghz/scenes/subghz_scene_rpc.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_rpc.c rename to applications/main/subghz/scenes/subghz_scene_rpc.c diff --git a/applications/subghz/scenes/subghz_scene_save_name.c b/applications/main/subghz/scenes/subghz_scene_save_name.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_save_name.c rename to applications/main/subghz/scenes/subghz_scene_save_name.c diff --git a/applications/subghz/scenes/subghz_scene_save_success.c b/applications/main/subghz/scenes/subghz_scene_save_success.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_save_success.c rename to applications/main/subghz/scenes/subghz_scene_save_success.c diff --git a/applications/subghz/scenes/subghz_scene_saved.c b/applications/main/subghz/scenes/subghz_scene_saved.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_saved.c rename to applications/main/subghz/scenes/subghz_scene_saved.c diff --git a/applications/subghz/scenes/subghz_scene_saved_menu.c b/applications/main/subghz/scenes/subghz_scene_saved_menu.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_saved_menu.c rename to applications/main/subghz/scenes/subghz_scene_saved_menu.c diff --git a/applications/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_set_type.c rename to applications/main/subghz/scenes/subghz_scene_set_type.c diff --git a/applications/subghz/scenes/subghz_scene_show_error.c b/applications/main/subghz/scenes/subghz_scene_show_error.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_show_error.c rename to applications/main/subghz/scenes/subghz_scene_show_error.c diff --git a/applications/subghz/scenes/subghz_scene_show_error_sub.c b/applications/main/subghz/scenes/subghz_scene_show_error_sub.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_show_error_sub.c rename to applications/main/subghz/scenes/subghz_scene_show_error_sub.c diff --git a/applications/subghz/scenes/subghz_scene_show_only_rx.c b/applications/main/subghz/scenes/subghz_scene_show_only_rx.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_show_only_rx.c rename to applications/main/subghz/scenes/subghz_scene_show_only_rx.c diff --git a/applications/subghz/scenes/subghz_scene_start.c b/applications/main/subghz/scenes/subghz_scene_start.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_start.c rename to applications/main/subghz/scenes/subghz_scene_start.c diff --git a/applications/subghz/scenes/subghz_scene_test.c b/applications/main/subghz/scenes/subghz_scene_test.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_test.c rename to applications/main/subghz/scenes/subghz_scene_test.c diff --git a/applications/subghz/scenes/subghz_scene_test_carrier.c b/applications/main/subghz/scenes/subghz_scene_test_carrier.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_test_carrier.c rename to applications/main/subghz/scenes/subghz_scene_test_carrier.c diff --git a/applications/subghz/scenes/subghz_scene_test_packet.c b/applications/main/subghz/scenes/subghz_scene_test_packet.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_test_packet.c rename to applications/main/subghz/scenes/subghz_scene_test_packet.c diff --git a/applications/subghz/scenes/subghz_scene_test_static.c b/applications/main/subghz/scenes/subghz_scene_test_static.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_test_static.c rename to applications/main/subghz/scenes/subghz_scene_test_static.c diff --git a/applications/subghz/scenes/subghz_scene_transmitter.c b/applications/main/subghz/scenes/subghz_scene_transmitter.c similarity index 100% rename from applications/subghz/scenes/subghz_scene_transmitter.c rename to applications/main/subghz/scenes/subghz_scene_transmitter.c diff --git a/applications/subghz/subghz.c b/applications/main/subghz/subghz.c similarity index 100% rename from applications/subghz/subghz.c rename to applications/main/subghz/subghz.c diff --git a/applications/subghz/subghz.h b/applications/main/subghz/subghz.h similarity index 100% rename from applications/subghz/subghz.h rename to applications/main/subghz/subghz.h diff --git a/applications/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c similarity index 99% rename from applications/subghz/subghz_cli.c rename to applications/main/subghz/subghz_cli.c index cda50c79..d921979f 100644 --- a/applications/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -862,5 +862,7 @@ void subghz_on_system_start() { furi_record_close(RECORD_STORAGE); #else UNUSED(subghz_cli_command); + UNUSED(subghz_on_system_start_istream_decode_band); + UNUSED(subghz_on_system_start_istream_read); #endif } diff --git a/applications/subghz/subghz_cli.h b/applications/main/subghz/subghz_cli.h similarity index 100% rename from applications/subghz/subghz_cli.h rename to applications/main/subghz/subghz_cli.h diff --git a/applications/subghz/subghz_history.c b/applications/main/subghz/subghz_history.c similarity index 100% rename from applications/subghz/subghz_history.c rename to applications/main/subghz/subghz_history.c diff --git a/applications/subghz/subghz_history.h b/applications/main/subghz/subghz_history.h similarity index 100% rename from applications/subghz/subghz_history.h rename to applications/main/subghz/subghz_history.h diff --git a/applications/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c similarity index 96% rename from applications/subghz/subghz_i.c rename to applications/main/subghz/subghz_i.c index dc0d71e5..6ed8fd53 100644 --- a/applications/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -7,9 +7,9 @@ #include #include #include +#include #include #include -#include "../notification/notification.h" #include "views/receiver.h" #include @@ -278,11 +278,6 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { break; } - if(!furi_hal_region_is_frequency_allowed(temp_data32)) { - FURI_LOG_E(TAG, "This frequency can only be used for RX in your region"); - load_key_state = SubGhzLoadKeyStateOnlyRx; - break; - } subghz->txrx->preset->frequency = temp_data32; if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) { @@ -354,12 +349,6 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { } return false; - case SubGhzLoadKeyStateOnlyRx: - if(show_dialog) { - subghz_dialog_message_show_only_rx(subghz); - } - return false; - case SubGhzLoadKeyStateOK: return true; @@ -461,15 +450,12 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { string_t file_path; string_init(file_path); + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options(&browser_options, SUBGHZ_APP_EXTENSION, &I_sub1_10px); + // Input events and views are managed by file_select bool res = dialog_file_browser_show( - subghz->dialogs, - subghz->file_path, - subghz->file_path, - SUBGHZ_APP_EXTENSION, - true, - &I_sub1_10px, - true); + subghz->dialogs, subghz->file_path, subghz->file_path, &browser_options); if(res) { res = subghz_key_load(subghz, string_get_cstr(subghz->file_path), true); diff --git a/applications/subghz/subghz_i.h b/applications/main/subghz/subghz_i.h similarity index 100% rename from applications/subghz/subghz_i.h rename to applications/main/subghz/subghz_i.h diff --git a/applications/subghz/subghz_setting.c b/applications/main/subghz/subghz_setting.c similarity index 100% rename from applications/subghz/subghz_setting.c rename to applications/main/subghz/subghz_setting.c diff --git a/applications/subghz/subghz_setting.h b/applications/main/subghz/subghz_setting.h similarity index 100% rename from applications/subghz/subghz_setting.h rename to applications/main/subghz/subghz_setting.h diff --git a/applications/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c similarity index 100% rename from applications/subghz/views/receiver.c rename to applications/main/subghz/views/receiver.c diff --git a/applications/subghz/views/receiver.h b/applications/main/subghz/views/receiver.h similarity index 100% rename from applications/subghz/views/receiver.h rename to applications/main/subghz/views/receiver.h diff --git a/applications/subghz/views/subghz_frequency_analyzer.c b/applications/main/subghz/views/subghz_frequency_analyzer.c similarity index 100% rename from applications/subghz/views/subghz_frequency_analyzer.c rename to applications/main/subghz/views/subghz_frequency_analyzer.c diff --git a/applications/subghz/views/subghz_frequency_analyzer.h b/applications/main/subghz/views/subghz_frequency_analyzer.h similarity index 100% rename from applications/subghz/views/subghz_frequency_analyzer.h rename to applications/main/subghz/views/subghz_frequency_analyzer.h diff --git a/applications/subghz/views/subghz_read_raw.c b/applications/main/subghz/views/subghz_read_raw.c similarity index 100% rename from applications/subghz/views/subghz_read_raw.c rename to applications/main/subghz/views/subghz_read_raw.c diff --git a/applications/subghz/views/subghz_read_raw.h b/applications/main/subghz/views/subghz_read_raw.h similarity index 100% rename from applications/subghz/views/subghz_read_raw.h rename to applications/main/subghz/views/subghz_read_raw.h diff --git a/applications/subghz/views/subghz_test_carrier.c b/applications/main/subghz/views/subghz_test_carrier.c similarity index 100% rename from applications/subghz/views/subghz_test_carrier.c rename to applications/main/subghz/views/subghz_test_carrier.c diff --git a/applications/subghz/views/subghz_test_carrier.h b/applications/main/subghz/views/subghz_test_carrier.h similarity index 100% rename from applications/subghz/views/subghz_test_carrier.h rename to applications/main/subghz/views/subghz_test_carrier.h diff --git a/applications/subghz/views/subghz_test_packet.c b/applications/main/subghz/views/subghz_test_packet.c similarity index 100% rename from applications/subghz/views/subghz_test_packet.c rename to applications/main/subghz/views/subghz_test_packet.c diff --git a/applications/subghz/views/subghz_test_packet.h b/applications/main/subghz/views/subghz_test_packet.h similarity index 100% rename from applications/subghz/views/subghz_test_packet.h rename to applications/main/subghz/views/subghz_test_packet.h diff --git a/applications/subghz/views/subghz_test_static.c b/applications/main/subghz/views/subghz_test_static.c similarity index 100% rename from applications/subghz/views/subghz_test_static.c rename to applications/main/subghz/views/subghz_test_static.c diff --git a/applications/subghz/views/subghz_test_static.h b/applications/main/subghz/views/subghz_test_static.h similarity index 100% rename from applications/subghz/views/subghz_test_static.h rename to applications/main/subghz/views/subghz_test_static.h diff --git a/applications/subghz/views/transmitter.c b/applications/main/subghz/views/transmitter.c similarity index 100% rename from applications/subghz/views/transmitter.c rename to applications/main/subghz/views/transmitter.c diff --git a/applications/subghz/views/transmitter.h b/applications/main/subghz/views/transmitter.h similarity index 100% rename from applications/subghz/views/transmitter.h rename to applications/main/subghz/views/transmitter.h diff --git a/applications/u2f/application.fam b/applications/main/u2f/application.fam similarity index 100% rename from applications/u2f/application.fam rename to applications/main/u2f/application.fam diff --git a/applications/u2f/scenes/u2f_scene.c b/applications/main/u2f/scenes/u2f_scene.c similarity index 100% rename from applications/u2f/scenes/u2f_scene.c rename to applications/main/u2f/scenes/u2f_scene.c diff --git a/applications/u2f/scenes/u2f_scene.h b/applications/main/u2f/scenes/u2f_scene.h similarity index 100% rename from applications/u2f/scenes/u2f_scene.h rename to applications/main/u2f/scenes/u2f_scene.h diff --git a/applications/u2f/scenes/u2f_scene_config.h b/applications/main/u2f/scenes/u2f_scene_config.h similarity index 100% rename from applications/u2f/scenes/u2f_scene_config.h rename to applications/main/u2f/scenes/u2f_scene_config.h diff --git a/applications/u2f/scenes/u2f_scene_error.c b/applications/main/u2f/scenes/u2f_scene_error.c similarity index 100% rename from applications/u2f/scenes/u2f_scene_error.c rename to applications/main/u2f/scenes/u2f_scene_error.c diff --git a/applications/u2f/scenes/u2f_scene_main.c b/applications/main/u2f/scenes/u2f_scene_main.c similarity index 100% rename from applications/u2f/scenes/u2f_scene_main.c rename to applications/main/u2f/scenes/u2f_scene_main.c diff --git a/applications/u2f/u2f.c b/applications/main/u2f/u2f.c similarity index 100% rename from applications/u2f/u2f.c rename to applications/main/u2f/u2f.c diff --git a/applications/u2f/u2f.h b/applications/main/u2f/u2f.h similarity index 100% rename from applications/u2f/u2f.h rename to applications/main/u2f/u2f.h diff --git a/applications/u2f/u2f_app.c b/applications/main/u2f/u2f_app.c similarity index 100% rename from applications/u2f/u2f_app.c rename to applications/main/u2f/u2f_app.c diff --git a/applications/u2f/u2f_app.h b/applications/main/u2f/u2f_app.h similarity index 100% rename from applications/u2f/u2f_app.h rename to applications/main/u2f/u2f_app.h diff --git a/applications/u2f/u2f_app_i.h b/applications/main/u2f/u2f_app_i.h similarity index 100% rename from applications/u2f/u2f_app_i.h rename to applications/main/u2f/u2f_app_i.h diff --git a/applications/u2f/u2f_data.c b/applications/main/u2f/u2f_data.c similarity index 100% rename from applications/u2f/u2f_data.c rename to applications/main/u2f/u2f_data.c diff --git a/applications/u2f/u2f_data.h b/applications/main/u2f/u2f_data.h similarity index 100% rename from applications/u2f/u2f_data.h rename to applications/main/u2f/u2f_data.h diff --git a/applications/u2f/u2f_hid.c b/applications/main/u2f/u2f_hid.c similarity index 100% rename from applications/u2f/u2f_hid.c rename to applications/main/u2f/u2f_hid.c diff --git a/applications/u2f/u2f_hid.h b/applications/main/u2f/u2f_hid.h similarity index 100% rename from applications/u2f/u2f_hid.h rename to applications/main/u2f/u2f_hid.h diff --git a/applications/u2f/views/u2f_view.c b/applications/main/u2f/views/u2f_view.c similarity index 100% rename from applications/u2f/views/u2f_view.c rename to applications/main/u2f/views/u2f_view.c diff --git a/applications/u2f/views/u2f_view.h b/applications/main/u2f/views/u2f_view.h similarity index 100% rename from applications/u2f/views/u2f_view.h rename to applications/main/u2f/views/u2f_view.h diff --git a/applications/meta/application.fam b/applications/meta/application.fam deleted file mode 100644 index 8b873b5f..00000000 --- a/applications/meta/application.fam +++ /dev/null @@ -1,41 +0,0 @@ -App( - appid="basic_services", - name="Basic services", - apptype=FlipperAppType.METAPACKAGE, - provides=[ - "rpc_start", - "bt", - "desktop", - "loader", - "power", - ], -) - - -App( - appid="basic_apps", - name="Basic applications for main menu", - apptype=FlipperAppType.METAPACKAGE, - provides=[ - "gpio", - "ibutton", - "infrared", - "lfrfid", - "nfc", - "subghz", - "bad_usb", - "u2f", - ], -) - - -App( - appid="basic_plugins", - name="Basic applications for plug-in menu", - apptype=FlipperAppType.METAPACKAGE, - provides=[ - "music_player", - "snake_game", - "bt_hid", - ], -) diff --git a/applications/nfc/scenes/nfc_scene_mf_desfire_app.c b/applications/nfc/scenes/nfc_scene_mf_desfire_app.c deleted file mode 100644 index 7faafdcf..00000000 --- a/applications/nfc/scenes/nfc_scene_mf_desfire_app.c +++ /dev/null @@ -1,114 +0,0 @@ -#include "../nfc_i.h" - -#define TAG "NfcSceneMfDesfireApp" - -enum SubmenuIndex { - SubmenuIndexAppInfo, - SubmenuIndexDynamic, // dynamic indexes start here -}; - -MifareDesfireApplication* nfc_scene_mf_desfire_app_get_app(Nfc* nfc) { - uint32_t app_idx = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp) >> - 1; - MifareDesfireApplication* app = nfc->dev->dev_data.mf_df_data.app_head; - for(uint32_t i = 0; i < app_idx && app; i++) { - app = app->next; - } - return app; -} - -void nfc_scene_mf_desfire_app_submenu_callback(void* context, uint32_t index) { - Nfc* nfc = context; - - view_dispatcher_send_custom_event(nfc->view_dispatcher, index); -} - -void nfc_scene_mf_desfire_app_on_enter(void* context) { - Nfc* nfc = context; - Submenu* submenu = nfc->submenu; - MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc); - if(!app) { - popup_set_icon(nfc->popup, 5, 5, &I_WarningDolphin_45x42); - popup_set_header(nfc->popup, "Internal Error!", 55, 12, AlignLeft, AlignBottom); - popup_set_text( - nfc->popup, - "No app selected.\nThis should\nnever happen,\nplease file a bug.", - 55, - 15, - AlignLeft, - AlignTop); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - FURI_LOG_E(TAG, "Bad state. No app selected?"); - return; - } - - text_box_set_font(nfc->text_box, TextBoxFontHex); - - submenu_add_item( - submenu, "App info", SubmenuIndexAppInfo, nfc_scene_mf_desfire_app_submenu_callback, nfc); - - uint16_t cap = NFC_TEXT_STORE_SIZE; - char* buf = nfc->text_store; - int idx = SubmenuIndexDynamic; - for(MifareDesfireFile* file = app->file_head; file; file = file->next) { - int size = snprintf(buf, cap, "File %d", file->id); - if(size < 0 || size >= cap) { - FURI_LOG_W( - TAG, - "Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated"); - break; - } - char* label = buf; - cap -= size + 1; - buf += size + 1; - submenu_add_item(submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc); - } - - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); -} - -bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp); - - if(event.type == SceneManagerEventTypeCustom) { - MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc); - TextBox* text_box = nfc->text_box; - string_reset(nfc->text_box_store); - if(event.event == SubmenuIndexAppInfo) { - mf_df_cat_application_info(app, nfc->text_box_store); - } else { - uint16_t index = event.event - SubmenuIndexDynamic; - MifareDesfireFile* file = app->file_head; - for(int i = 0; file && i < index; i++) { - file = file->next; - } - if(!file) { - return false; - } - mf_df_cat_file(file, nfc->text_box_store); - } - text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state | 1); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); - consumed = true; - } else if(event.type == SceneManagerEventTypeBack) { - if(state & 1) { - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state & ~1); - consumed = true; - } - } - - return consumed; -} - -void nfc_scene_mf_desfire_app_on_exit(void* context) { - Nfc* nfc = context; - - // Clear views - text_box_reset(nfc->text_box); - string_reset(nfc->text_box_store); - submenu_reset(nfc->submenu); -} diff --git a/applications/picopass/application.fam b/applications/picopass/application.fam deleted file mode 100644 index ffc4b518..00000000 --- a/applications/picopass/application.fam +++ /dev/null @@ -1,11 +0,0 @@ -App( - appid="picopass", - name="PicoPass Reader", - apptype=FlipperAppType.PLUGIN, - entry_point="picopass_app", - cdefines=["APP_PICOPASS"], - requires=["storage", "gui"], - stack_size=4 * 1024, - icon="A_Plugins_14", - order=30, -) diff --git a/applications/plugins/application.fam b/applications/plugins/application.fam new file mode 100644 index 00000000..c88f6d28 --- /dev/null +++ b/applications/plugins/application.fam @@ -0,0 +1,10 @@ +App( + appid="basic_plugins", + name="Basic applications for plug-in menu", + apptype=FlipperAppType.METAPACKAGE, + provides=[ + "music_player", + "snake_game", + "bt_hid", + ], +) diff --git a/applications/plugins/bt_hid_app/application.fam b/applications/plugins/bt_hid_app/application.fam new file mode 100644 index 00000000..e6a3b175 --- /dev/null +++ b/applications/plugins/bt_hid_app/application.fam @@ -0,0 +1,15 @@ +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, + fap_icon="bt_remote_10px.png", + fap_category="Tools", +) diff --git a/applications/bt/bt_hid_app/bt_hid.c b/applications/plugins/bt_hid_app/bt_hid.c similarity index 99% rename from applications/bt/bt_hid_app/bt_hid.c rename to applications/plugins/bt_hid_app/bt_hid.c index 0827bd0a..b653fb37 100644 --- a/applications/bt/bt_hid_app/bt_hid.c +++ b/applications/plugins/bt_hid_app/bt_hid.c @@ -1,6 +1,6 @@ #include "bt_hid.h" #include -#include +#include #define TAG "BtHidApp" diff --git a/applications/bt/bt_hid_app/bt_hid.h b/applications/plugins/bt_hid_app/bt_hid.h similarity index 94% rename from applications/bt/bt_hid_app/bt_hid.h rename to applications/plugins/bt_hid_app/bt_hid.h index 81d092db..0f4c7be9 100644 --- a/applications/bt/bt_hid_app/bt_hid.h +++ b/applications/plugins/bt_hid_app/bt_hid.h @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include diff --git a/applications/plugins/bt_hid_app/bt_remote_10px.png b/applications/plugins/bt_hid_app/bt_remote_10px.png new file mode 100644 index 00000000..d4d30afe Binary files /dev/null and b/applications/plugins/bt_hid_app/bt_remote_10px.png differ diff --git a/applications/bt/bt_hid_app/views/bt_hid_keyboard.c b/applications/plugins/bt_hid_app/views/bt_hid_keyboard.c similarity index 99% rename from applications/bt/bt_hid_app/views/bt_hid_keyboard.c rename to applications/plugins/bt_hid_app/views/bt_hid_keyboard.c index 1088e295..3617dc0f 100644 --- a/applications/bt/bt_hid_app/views/bt_hid_keyboard.c +++ b/applications/plugins/bt_hid_app/views/bt_hid_keyboard.c @@ -109,7 +109,7 @@ const BtHidKeyboardKey bt_hid_keyboard_keyset[ROW_COUNT][COLUMN_COUNT] = { {.width = 1, .icon = NULL, .key = "-", .shift_key = "_", .value = HID_KEYBOARD_MINUS}, }, { - {.width = 1, .icon = &I_Pin_arrow_up7x9, .value = HID_KEYBOARD_L_SHIFT}, + {.width = 1, .icon = &I_Pin_arrow_up_7x9, .value = HID_KEYBOARD_L_SHIFT}, {.width = 1, .icon = NULL, .key = ",", .shift_key = "<", .value = HID_KEYPAD_COMMA}, {.width = 1, .icon = NULL, .key = ".", .shift_key = ">", .value = HID_KEYBOARD_DOT}, {.width = 4, .icon = NULL, .key = " ", .value = HID_KEYBOARD_SPACEBAR}, diff --git a/applications/bt/bt_hid_app/views/bt_hid_keyboard.h b/applications/plugins/bt_hid_app/views/bt_hid_keyboard.h similarity index 100% rename from applications/bt/bt_hid_app/views/bt_hid_keyboard.h rename to applications/plugins/bt_hid_app/views/bt_hid_keyboard.h diff --git a/applications/bt/bt_hid_app/views/bt_hid_keynote.c b/applications/plugins/bt_hid_app/views/bt_hid_keynote.c similarity index 100% rename from applications/bt/bt_hid_app/views/bt_hid_keynote.c rename to applications/plugins/bt_hid_app/views/bt_hid_keynote.c diff --git a/applications/bt/bt_hid_app/views/bt_hid_keynote.h b/applications/plugins/bt_hid_app/views/bt_hid_keynote.h similarity index 100% rename from applications/bt/bt_hid_app/views/bt_hid_keynote.h rename to applications/plugins/bt_hid_app/views/bt_hid_keynote.h diff --git a/applications/bt/bt_hid_app/views/bt_hid_media.c b/applications/plugins/bt_hid_app/views/bt_hid_media.c similarity index 100% rename from applications/bt/bt_hid_app/views/bt_hid_media.c rename to applications/plugins/bt_hid_app/views/bt_hid_media.c diff --git a/applications/bt/bt_hid_app/views/bt_hid_media.h b/applications/plugins/bt_hid_app/views/bt_hid_media.h similarity index 100% rename from applications/bt/bt_hid_app/views/bt_hid_media.h rename to applications/plugins/bt_hid_app/views/bt_hid_media.h diff --git a/applications/bt/bt_hid_app/views/bt_hid_mouse.c b/applications/plugins/bt_hid_app/views/bt_hid_mouse.c similarity index 99% rename from applications/bt/bt_hid_app/views/bt_hid_mouse.c rename to applications/plugins/bt_hid_app/views/bt_hid_mouse.c index f9d84f9f..395cb52c 100644 --- a/applications/bt/bt_hid_app/views/bt_hid_mouse.c +++ b/applications/plugins/bt_hid_app/views/bt_hid_mouse.c @@ -53,7 +53,7 @@ static void bt_hid_mouse_draw_callback(Canvas* canvas, void* context) { canvas_set_bitmap_mode(canvas, 0); canvas_set_color(canvas, ColorWhite); } - canvas_draw_icon(canvas, 84, 10, &I_Pin_arrow_up7x9); + canvas_draw_icon(canvas, 84, 10, &I_Pin_arrow_up_7x9); canvas_set_color(canvas, ColorBlack); // Down diff --git a/applications/bt/bt_hid_app/views/bt_hid_mouse.h b/applications/plugins/bt_hid_app/views/bt_hid_mouse.h similarity index 100% rename from applications/bt/bt_hid_app/views/bt_hid_mouse.h rename to applications/plugins/bt_hid_app/views/bt_hid_mouse.h diff --git a/applications/music_player/application.fam b/applications/plugins/music_player/application.fam similarity index 84% rename from applications/music_player/application.fam rename to applications/plugins/music_player/application.fam index 70e29743..76787e09 100644 --- a/applications/music_player/application.fam +++ b/applications/plugins/music_player/application.fam @@ -11,6 +11,8 @@ App( provides=["music_player_start"], stack_size=2 * 1024, order=20, + fap_icon="../../../assets/icons/Archive/music_10px.png", + fap_category="Misc", ) App( diff --git a/applications/music_player/music_player.c b/applications/plugins/music_player/music_player.c similarity index 96% rename from applications/music_player/music_player.c rename to applications/plugins/music_player/music_player.c index 121efa0f..40e9085f 100644 --- a/applications/music_player/music_player.c +++ b/applications/plugins/music_player/music_player.c @@ -305,15 +305,13 @@ int32_t music_player_app(void* p) { } else { string_set_str(file_path, MUSIC_PLAYER_APP_PATH_FOLDER); + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options( + &browser_options, MUSIC_PLAYER_APP_EXTENSION, &I_music_10px); + browser_options.hide_ext = false; + DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - bool res = dialog_file_browser_show( - dialogs, - file_path, - file_path, - MUSIC_PLAYER_APP_EXTENSION, - true, - &I_music_10px, - false); + bool res = dialog_file_browser_show(dialogs, file_path, file_path, &browser_options); furi_record_close(RECORD_DIALOGS); if(!res) { diff --git a/applications/music_player/music_player_cli.c b/applications/plugins/music_player/music_player_cli.c similarity index 100% rename from applications/music_player/music_player_cli.c rename to applications/plugins/music_player/music_player_cli.c diff --git a/applications/music_player/music_player_worker.c b/applications/plugins/music_player/music_player_worker.c similarity index 100% rename from applications/music_player/music_player_worker.c rename to applications/plugins/music_player/music_player_worker.c diff --git a/applications/music_player/music_player_worker.h b/applications/plugins/music_player/music_player_worker.h similarity index 100% rename from applications/music_player/music_player_worker.h rename to applications/plugins/music_player/music_player_worker.h diff --git a/applications/plugins/picopass/application.fam b/applications/plugins/picopass/application.fam new file mode 100644 index 00000000..7a81e080 --- /dev/null +++ b/applications/plugins/picopass/application.fam @@ -0,0 +1,17 @@ +App( + appid="picopass", + name="PicoPass Reader", + apptype=FlipperAppType.EXTERNAL, + entry_point="picopass_app", + requires=[ + "storage", + "gui", + ], + stack_size=4 * 1024, + order=30, + fap_icon="../../../assets/icons/Archive/125_10px.png", + fap_libs=[ + "mbedtls", + ], + fap_category="Tools", +) diff --git a/lib/loclass/optimized_cipher.c b/applications/plugins/picopass/loclass/optimized_cipher.c similarity index 73% rename from lib/loclass/optimized_cipher.c rename to applications/plugins/picopass/loclass/optimized_cipher.c index e4f6a58c..eba95538 100644 --- a/lib/loclass/optimized_cipher.c +++ b/applications/plugins/picopass/loclass/optimized_cipher.c @@ -82,23 +82,17 @@ #include "optimized_cipherutils.h" static const uint8_t loclass_opt_select_LUT[256] = { - 00, 03, 02, 01, 02, 03, 00, 01, 04, 07, 07, 04, 06, 07, 05, 04, - 01, 02, 03, 00, 02, 03, 00, 01, 05, 06, 06, 05, 06, 07, 05, 04, - 06, 05, 04, 07, 04, 05, 06, 07, 06, 05, 05, 06, 04, 05, 07, 06, - 07, 04, 05, 06, 04, 05, 06, 07, 07, 04, 04, 07, 04, 05, 07, 06, - 06, 05, 04, 07, 04, 05, 06, 07, 02, 01, 01, 02, 00, 01, 03, 02, - 03, 00, 01, 02, 00, 01, 02, 03, 07, 04, 04, 07, 04, 05, 07, 06, - 00, 03, 02, 01, 02, 03, 00, 01, 00, 03, 03, 00, 02, 03, 01, 00, - 05, 06, 07, 04, 06, 07, 04, 05, 05, 06, 06, 05, 06, 07, 05, 04, - 02, 01, 00, 03, 00, 01, 02, 03, 06, 05, 05, 06, 04, 05, 07, 06, - 03, 00, 01, 02, 00, 01, 02, 03, 07, 04, 04, 07, 04, 05, 07, 06, - 02, 01, 00, 03, 00, 01, 02, 03, 02, 01, 01, 02, 00, 01, 03, 02, - 03, 00, 01, 02, 00, 01, 02, 03, 03, 00, 00, 03, 00, 01, 03, 02, - 04, 07, 06, 05, 06, 07, 04, 05, 00, 03, 03, 00, 02, 03, 01, 00, - 01, 02, 03, 00, 02, 03, 00, 01, 05, 06, 06, 05, 06, 07, 05, 04, - 04, 07, 06, 05, 06, 07, 04, 05, 04, 07, 07, 04, 06, 07, 05, 04, - 01, 02, 03, 00, 02, 03, 00, 01, 01, 02, 02, 01, 02, 03, 01, 00 -}; + 00, 03, 02, 01, 02, 03, 00, 01, 04, 07, 07, 04, 06, 07, 05, 04, 01, 02, 03, 00, 02, 03, 00, 01, + 05, 06, 06, 05, 06, 07, 05, 04, 06, 05, 04, 07, 04, 05, 06, 07, 06, 05, 05, 06, 04, 05, 07, 06, + 07, 04, 05, 06, 04, 05, 06, 07, 07, 04, 04, 07, 04, 05, 07, 06, 06, 05, 04, 07, 04, 05, 06, 07, + 02, 01, 01, 02, 00, 01, 03, 02, 03, 00, 01, 02, 00, 01, 02, 03, 07, 04, 04, 07, 04, 05, 07, 06, + 00, 03, 02, 01, 02, 03, 00, 01, 00, 03, 03, 00, 02, 03, 01, 00, 05, 06, 07, 04, 06, 07, 04, 05, + 05, 06, 06, 05, 06, 07, 05, 04, 02, 01, 00, 03, 00, 01, 02, 03, 06, 05, 05, 06, 04, 05, 07, 06, + 03, 00, 01, 02, 00, 01, 02, 03, 07, 04, 04, 07, 04, 05, 07, 06, 02, 01, 00, 03, 00, 01, 02, 03, + 02, 01, 01, 02, 00, 01, 03, 02, 03, 00, 01, 02, 00, 01, 02, 03, 03, 00, 00, 03, 00, 01, 03, 02, + 04, 07, 06, 05, 06, 07, 04, 05, 00, 03, 03, 00, 02, 03, 01, 00, 01, 02, 03, 00, 02, 03, 00, 01, + 05, 06, 06, 05, 06, 07, 05, 04, 04, 07, 06, 05, 06, 07, 04, 05, 04, 07, 07, 04, 06, 07, 05, 04, + 01, 02, 03, 00, 02, 03, 00, 01, 01, 02, 02, 01, 02, 03, 01, 00}; /********************** the table above has been generated with this code: ******** #include "util.h" @@ -116,12 +110,12 @@ static void init_opt_select_LUT(void) { } ***********************************************************************************/ -#define loclass_opt__select(x,y,r) (4 & (((r & (r << 2)) >> 5) ^ ((r & ~(r << 2)) >> 4) ^ ( (r | r << 2) >> 3)))\ - |(2 & (((r | r << 2) >> 6) ^ ( (r | r << 2) >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1)))\ - |(1 & (((r & ~(r << 2)) >> 4) ^ ((r & (r << 2)) >> 3) ^ r ^ x)) +#define loclass_opt__select(x, y, r) \ + (4 & (((r & (r << 2)) >> 5) ^ ((r & ~(r << 2)) >> 4) ^ ((r | r << 2) >> 3))) | \ + (2 & (((r | r << 2) >> 6) ^ ((r | r << 2) >> 1) ^ (r >> 5) ^ r ^ ((x ^ y) << 1))) | \ + (1 & (((r & ~(r << 2)) >> 4) ^ ((r & (r << 2)) >> 3) ^ r ^ x)) - -static void loclass_opt_successor(const uint8_t *k, LoclassState_t *s, uint8_t y) { +static void loclass_opt_successor(const uint8_t* k, LoclassState_t* s, uint8_t y) { uint16_t Tt = s->t & 0xc533; Tt = Tt ^ (Tt >> 1); Tt = Tt ^ (Tt >> 4); @@ -144,12 +138,17 @@ static void loclass_opt_successor(const uint8_t *k, LoclassState_t *s, uint8_t y opt_select |= (loclass_opt_select_LUT[s->r] ^ Tt) & 0x01; uint8_t r = s->r; - s->r = (k[opt_select] ^ s->b) + s->l ; + s->r = (k[opt_select] ^ s->b) + s->l; s->l = s->r + r; } -static void loclass_opt_suc(const uint8_t *k, LoclassState_t *s, const uint8_t *in, uint8_t length, bool add32Zeroes) { - for (int i = 0; i < length; i++) { +static void loclass_opt_suc( + const uint8_t* k, + LoclassState_t* s, + const uint8_t* in, + uint8_t length, + bool add32Zeroes) { + for(int i = 0; i < length; i++) { uint8_t head; head = in[i]; loclass_opt_successor(k, s, head); @@ -176,16 +175,16 @@ static void loclass_opt_suc(const uint8_t *k, LoclassState_t *s, const uint8_t * loclass_opt_successor(k, s, head); } //For tag MAC, an additional 32 zeroes - if (add32Zeroes) { - for (int i = 0; i < 16; i++) { + if(add32Zeroes) { + for(int i = 0; i < 16; i++) { loclass_opt_successor(k, s, 0); loclass_opt_successor(k, s, 0); } } } -static void loclass_opt_output(const uint8_t *k, LoclassState_t *s, uint8_t *buffer) { - for (uint8_t times = 0; times < 4; times++) { +static void loclass_opt_output(const uint8_t* k, LoclassState_t* s, uint8_t* buffer) { + for(uint8_t times = 0; times < 4; times++) { uint8_t bout = 0; bout |= (s->r & 0x4) >> 2; loclass_opt_successor(k, s, 0); @@ -207,10 +206,10 @@ static void loclass_opt_output(const uint8_t *k, LoclassState_t *s, uint8_t *bu } } -static void loclass_opt_MAC(uint8_t *k, uint8_t *input, uint8_t *out) { - LoclassState_t _init = { - ((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l - ((k[0] ^ 0x4c) + 0x21) & 0xFF,// r +static void loclass_opt_MAC(uint8_t* k, uint8_t* input, uint8_t* out) { + LoclassState_t _init = { + ((k[0] ^ 0x4c) + 0xEC) & 0xFF, // l + ((k[0] ^ 0x4c) + 0x21) & 0xFF, // r 0x4c, // b 0xE012 // t }; @@ -219,10 +218,10 @@ static void loclass_opt_MAC(uint8_t *k, uint8_t *input, uint8_t *out) { loclass_opt_output(k, &_init, out); } -static void loclass_opt_MAC_N(uint8_t *k, uint8_t *input, uint8_t in_size, uint8_t *out) { - LoclassState_t _init = { - ((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l - ((k[0] ^ 0x4c) + 0x21) & 0xFF,// r +static void loclass_opt_MAC_N(uint8_t* k, uint8_t* input, uint8_t in_size, uint8_t* out) { + LoclassState_t _init = { + ((k[0] ^ 0x4c) + 0xEC) & 0xFF, // l + ((k[0] ^ 0x4c) + 0x21) & 0xFF, // r 0x4c, // b 0xE012 // t }; @@ -231,28 +230,31 @@ static void loclass_opt_MAC_N(uint8_t *k, uint8_t *input, uint8_t in_size, uint8 loclass_opt_output(k, &_init, out); } -void loclass_opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) { - uint8_t dest [] = {0, 0, 0, 0, 0, 0, 0, 0}; +void loclass_opt_doReaderMAC(uint8_t* cc_nr_p, uint8_t* div_key_p, uint8_t mac[4]) { + uint8_t dest[] = {0, 0, 0, 0, 0, 0, 0, 0}; loclass_opt_MAC(div_key_p, cc_nr_p, dest); memcpy(mac, dest, 4); } -void loclass_opt_doReaderMAC_2(LoclassState_t _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p) { +void loclass_opt_doReaderMAC_2( + LoclassState_t _init, + uint8_t* nr, + uint8_t mac[4], + const uint8_t* div_key_p) { loclass_opt_suc(div_key_p, &_init, nr, 4, false); loclass_opt_output(div_key_p, &_init, mac); } - -void loclass_doMAC_N(uint8_t *in_p, uint8_t in_size, uint8_t *div_key_p, uint8_t mac[4]) { - uint8_t dest [] = {0, 0, 0, 0, 0, 0, 0, 0}; +void loclass_doMAC_N(uint8_t* in_p, uint8_t in_size, uint8_t* div_key_p, uint8_t mac[4]) { + uint8_t dest[] = {0, 0, 0, 0, 0, 0, 0, 0}; loclass_opt_MAC_N(div_key_p, in_p, in_size, dest); memcpy(mac, dest, 4); } -void loclass_opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) { - LoclassState_t _init = { - ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l - ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r +void loclass_opt_doTagMAC(uint8_t* cc_p, const uint8_t* div_key_p, uint8_t mac[4]) { + LoclassState_t _init = { + ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF, // l + ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF, // r 0x4c, // b 0xE012 // t }; @@ -268,10 +270,10 @@ void loclass_opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4 * @param div_key_p * @return the cipher state */ -LoclassState_t loclass_opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) { - LoclassState_t _init = { - ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l - ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r +LoclassState_t loclass_opt_doTagMAC_1(uint8_t* cc_p, const uint8_t* div_key_p) { + LoclassState_t _init = { + ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF, // l + ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF, // r 0x4c, // b 0xE012 // t }; @@ -288,21 +290,24 @@ LoclassState_t loclass_opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) { * @param mac - where to store the MAC * @param div_key_p - the key to use */ -void loclass_opt_doTagMAC_2(LoclassState_t _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p) { +void loclass_opt_doTagMAC_2( + LoclassState_t _init, + uint8_t* nr, + uint8_t mac[4], + const uint8_t* div_key_p) { loclass_opt_suc(div_key_p, &_init, nr, 4, true); loclass_opt_output(div_key_p, &_init, mac); } -void loclass_iclass_calc_div_key(uint8_t *csn, uint8_t *key, uint8_t *div_key, bool elite) { - if (elite) { +void loclass_iclass_calc_div_key(uint8_t* csn, uint8_t* key, uint8_t* div_key, bool elite) { + if(elite) { uint8_t keytable[128] = {0}; uint8_t key_index[8] = {0}; - uint8_t key_sel[8] = { 0 }; - uint8_t key_sel_p[8] = { 0 }; + uint8_t key_sel[8] = {0}; + uint8_t key_sel_p[8] = {0}; loclass_hash2(key, keytable); loclass_hash1(csn, key_index); - for (uint8_t i = 0; i < 8 ; i++) - key_sel[i] = keytable[key_index[i]]; + for(uint8_t i = 0; i < 8; i++) key_sel[i] = keytable[key_index[i]]; //Permute from iclass format to standard format loclass_permutekey_rev(key_sel, key_sel_p); diff --git a/lib/loclass/optimized_cipher.h b/applications/plugins/picopass/loclass/optimized_cipher.h similarity index 84% rename from lib/loclass/optimized_cipher.h rename to applications/plugins/picopass/loclass/optimized_cipher.h index e7b8cbd6..2158f0ac 100644 --- a/lib/loclass/optimized_cipher.h +++ b/applications/plugins/picopass/loclass/optimized_cipher.h @@ -56,14 +56,18 @@ typedef struct { /** The reader MAC is MAC(key, CC * NR ) **/ -void loclass_opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]); +void loclass_opt_doReaderMAC(uint8_t* cc_nr_p, uint8_t* div_key_p, uint8_t mac[4]); -void loclass_opt_doReaderMAC_2(LoclassState_t _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p); +void loclass_opt_doReaderMAC_2( + LoclassState_t _init, + uint8_t* nr, + uint8_t mac[4], + const uint8_t* div_key_p); /** * The tag MAC is MAC(key, CC * NR * 32x0)) */ -void loclass_opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]); +void loclass_opt_doTagMAC(uint8_t* cc_p, const uint8_t* div_key_p, uint8_t mac[4]); /** * The tag MAC can be divided (both can, but no point in dividing the reader mac) into @@ -73,7 +77,7 @@ void loclass_opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4 * @param div_key_p * @return the cipher state */ -LoclassState_t loclass_opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p); +LoclassState_t loclass_opt_doTagMAC_1(uint8_t* cc_p, const uint8_t* div_key_p); /** * The second part of the tag MAC calculation, since the CC is already calculated into the state, * this function is fed only the NR, and internally feeds the remaining 32 0-bits to generate the tag @@ -83,8 +87,12 @@ LoclassState_t loclass_opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p); * @param mac - where to store the MAC * @param div_key_p - the key to use */ -void loclass_opt_doTagMAC_2(LoclassState_t _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p); +void loclass_opt_doTagMAC_2( + LoclassState_t _init, + uint8_t* nr, + uint8_t mac[4], + const uint8_t* div_key_p); -void loclass_doMAC_N(uint8_t *in_p, uint8_t in_size, uint8_t *div_key_p, uint8_t mac[4]); -void loclass_iclass_calc_div_key(uint8_t *csn, uint8_t *key, uint8_t *div_key, bool elite); +void loclass_doMAC_N(uint8_t* in_p, uint8_t in_size, uint8_t* div_key_p, uint8_t mac[4]); +void loclass_iclass_calc_div_key(uint8_t* csn, uint8_t* key, uint8_t* div_key, bool elite); #endif // OPTIMIZED_CIPHER_H diff --git a/lib/loclass/optimized_cipherutils.c b/applications/plugins/picopass/loclass/optimized_cipherutils.c similarity index 84% rename from lib/loclass/optimized_cipherutils.c rename to applications/plugins/picopass/loclass/optimized_cipherutils.c index c5bcbacc..e6a87c4a 100644 --- a/lib/loclass/optimized_cipherutils.c +++ b/applications/plugins/picopass/loclass/optimized_cipherutils.c @@ -40,7 +40,7 @@ * @param stream * @return */ -bool loclass_headBit(LoclassBitstreamIn_t *stream) { +bool loclass_headBit(LoclassBitstreamIn_t* stream) { int bytepos = stream->position >> 3; // divide by 8 int bitpos = (stream->position++) & 7; // mask out 00000111 return (*(stream->buffer + bytepos) >> (7 - bitpos)) & 1; @@ -50,7 +50,7 @@ bool loclass_headBit(LoclassBitstreamIn_t *stream) { * @param stream * @return */ -bool loclass_tailBit(LoclassBitstreamIn_t *stream) { +bool loclass_tailBit(LoclassBitstreamIn_t* stream) { int bitpos = stream->numbits - 1 - (stream->position++); int bytepos = bitpos >> 3; @@ -62,7 +62,7 @@ bool loclass_tailBit(LoclassBitstreamIn_t *stream) { * @param stream * @param bit */ -void loclass_pushBit(LoclassBitstreamOut_t *stream, bool bit) { +void loclass_pushBit(LoclassBitstreamOut_t* stream, bool bit) { int bytepos = stream->position >> 3; // divide by 8 int bitpos = stream->position & 7; *(stream->buffer + bytepos) |= (bit) << (7 - bitpos); @@ -76,7 +76,7 @@ void loclass_pushBit(LoclassBitstreamOut_t *stream, bool bit) { * @param stream * @param bits */ -void loclass_push6bits(LoclassBitstreamOut_t *stream, uint8_t bits) { +void loclass_push6bits(LoclassBitstreamOut_t* stream, uint8_t bits) { loclass_pushBit(stream, bits & 0x20); loclass_pushBit(stream, bits & 0x10); loclass_pushBit(stream, bits & 0x08); @@ -90,7 +90,7 @@ void loclass_push6bits(LoclassBitstreamOut_t *stream, uint8_t bits) { * @param stream * @return number of bits left in stream */ -int loclass_bitsLeft(LoclassBitstreamIn_t *stream) { +int loclass_bitsLeft(LoclassBitstreamIn_t* stream) { return stream->numbits - stream->position; } /** @@ -98,16 +98,16 @@ int loclass_bitsLeft(LoclassBitstreamIn_t *stream) { * @param stream * @return Number of bits stored in stream */ -void loclass_x_num_to_bytes(uint64_t n, size_t len, uint8_t *dest) { - while (len--) { - dest[len] = (uint8_t) n; +void loclass_x_num_to_bytes(uint64_t n, size_t len, uint8_t* dest) { + while(len--) { + dest[len] = (uint8_t)n; n >>= 8; } } -uint64_t loclass_x_bytes_to_num(uint8_t *src, size_t len) { +uint64_t loclass_x_bytes_to_num(uint8_t* src, size_t len) { uint64_t num = 0; - while (len--) { + while(len--) { num = (num << 8) | (*src); src++; } @@ -121,17 +121,16 @@ uint8_t loclass_reversebytes(uint8_t b) { return b; } -void loclass_reverse_arraybytes(uint8_t *arr, size_t len) { +void loclass_reverse_arraybytes(uint8_t* arr, size_t len) { uint8_t i; - for (i = 0; i < len ; i++) { + for(i = 0; i < len; i++) { arr[i] = loclass_reversebytes(arr[i]); } } -void loclass_reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len) { +void loclass_reverse_arraycopy(uint8_t* arr, uint8_t* dest, size_t len) { uint8_t i; - for (i = 0; i < len ; i++) { + for(i = 0; i < len; i++) { dest[i] = loclass_reversebytes(arr[i]); } } - diff --git a/lib/loclass/optimized_cipherutils.h b/applications/plugins/picopass/loclass/optimized_cipherutils.h similarity index 78% rename from lib/loclass/optimized_cipherutils.h rename to applications/plugins/picopass/loclass/optimized_cipherutils.h index cb9d2724..05b68207 100644 --- a/lib/loclass/optimized_cipherutils.h +++ b/applications/plugins/picopass/loclass/optimized_cipherutils.h @@ -39,26 +39,26 @@ #include typedef struct { - uint8_t *buffer; + uint8_t* buffer; uint8_t numbits; uint8_t position; } LoclassBitstreamIn_t; typedef struct { - uint8_t *buffer; + uint8_t* buffer; uint8_t numbits; uint8_t position; } LoclassBitstreamOut_t; -bool loclass_headBit(LoclassBitstreamIn_t *stream); -bool loclass_tailBit(LoclassBitstreamIn_t *stream); -void loclass_pushBit(LoclassBitstreamOut_t *stream, bool bit); -int loclass_bitsLeft(LoclassBitstreamIn_t *stream); +bool loclass_headBit(LoclassBitstreamIn_t* stream); +bool loclass_tailBit(LoclassBitstreamIn_t* stream); +void loclass_pushBit(LoclassBitstreamOut_t* stream, bool bit); +int loclass_bitsLeft(LoclassBitstreamIn_t* stream); -void loclass_push6bits(LoclassBitstreamOut_t *stream, uint8_t bits); -void loclass_x_num_to_bytes(uint64_t n, size_t len, uint8_t *dest); -uint64_t loclass_x_bytes_to_num(uint8_t *src, size_t len); +void loclass_push6bits(LoclassBitstreamOut_t* stream, uint8_t bits); +void loclass_x_num_to_bytes(uint64_t n, size_t len, uint8_t* dest); +uint64_t loclass_x_bytes_to_num(uint8_t* src, size_t len); uint8_t loclass_reversebytes(uint8_t b); -void loclass_reverse_arraybytes(uint8_t *arr, size_t len); -void loclass_reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len); +void loclass_reverse_arraybytes(uint8_t* arr, size_t len); +void loclass_reverse_arraycopy(uint8_t* arr, uint8_t* dest, size_t len); #endif // CIPHERUTILS_H diff --git a/lib/loclass/optimized_elite.c b/applications/plugins/picopass/loclass/optimized_elite.c similarity index 92% rename from lib/loclass/optimized_elite.c rename to applications/plugins/picopass/loclass/optimized_elite.c index fc1e5d74..c175f398 100644 --- a/lib/loclass/optimized_elite.c +++ b/applications/plugins/picopass/loclass/optimized_elite.c @@ -62,7 +62,7 @@ */ void loclass_permutekey(const uint8_t key[8], uint8_t dest[8]) { int i; - for (i = 0 ; i < 8 ; i++) { + for(i = 0; i < 8; i++) { dest[i] = (((key[7] & (0x80 >> i)) >> (7 - i)) << 7) | (((key[6] & (0x80 >> i)) >> (7 - i)) << 6) | (((key[5] & (0x80 >> i)) >> (7 - i)) << 5) | @@ -81,7 +81,7 @@ void loclass_permutekey(const uint8_t key[8], uint8_t dest[8]) { */ void loclass_permutekey_rev(const uint8_t key[8], uint8_t dest[8]) { int i; - for (i = 0 ; i < 8 ; i++) { + for(i = 0; i < 8; i++) { dest[7 - i] = (((key[0] & (0x80 >> i)) >> (7 - i)) << 7) | (((key[1] & (0x80 >> i)) >> (7 - i)) << 6) | (((key[2] & (0x80 >> i)) >> (7 - i)) << 5) | @@ -153,12 +153,11 @@ Definition 14. Define the rotate key function loclass_rk : (F 82 ) 8 × N → (F loclass_rk(x [0] . . . x [7] , 0) = x [0] . . . x [7] loclass_rk(x [0] . . . x [7] , n + 1) = loclass_rk(loclass_rl(x [0] ) . . . loclass_rl(x [7] ), n) **/ -static void loclass_rk(uint8_t *key, uint8_t n, uint8_t *outp_key) { +static void loclass_rk(uint8_t* key, uint8_t n, uint8_t* outp_key) { memcpy(outp_key, key, 8); uint8_t j; - while (n-- > 0) { - for (j = 0; j < 8 ; j++) - outp_key[j] = loclass_rl(outp_key[j]); + while(n-- > 0) { + for(j = 0; j < 8; j++) outp_key[j] = loclass_rl(outp_key[j]); } return; } @@ -166,14 +165,14 @@ static void loclass_rk(uint8_t *key, uint8_t n, uint8_t *outp_key) { static mbedtls_des_context loclass_ctx_enc; static mbedtls_des_context loclass_ctx_dec; -static void loclass_desdecrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) { +static void loclass_desdecrypt_iclass(uint8_t* iclass_key, uint8_t* input, uint8_t* output) { uint8_t key_std_format[8] = {0}; loclass_permutekey_rev(iclass_key, key_std_format); mbedtls_des_setkey_dec(&loclass_ctx_dec, key_std_format); mbedtls_des_crypt_ecb(&loclass_ctx_dec, input, output); } -static void loclass_desencrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) { +static void loclass_desencrypt_iclass(uint8_t* iclass_key, uint8_t* input, uint8_t* output) { uint8_t key_std_format[8] = {0}; loclass_permutekey_rev(iclass_key, key_std_format); mbedtls_des_setkey_enc(&loclass_ctx_enc, key_std_format); @@ -186,7 +185,7 @@ static void loclass_desencrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8 * @param loclass_hash1 loclass_hash1 * @param key_sel output key_sel=h[loclass_hash1[i]] */ -void hash2(uint8_t *key64, uint8_t *outp_keytable) { +void hash2(uint8_t* key64, uint8_t* outp_keytable) { /** *Expected: * High Security Key Table @@ -207,8 +206,7 @@ void hash2(uint8_t *key64, uint8_t *outp_keytable) { //calculate complement of key int i; - for (i = 0; i < 8; i++) - key64_negated[i] = ~key64[i]; + for(i = 0; i < 8; i++) key64_negated[i] = ~key64[i]; // Once again, key is on iclass-format loclass_desencrypt_iclass(key64, key64_negated, z[0]); @@ -219,14 +217,14 @@ void hash2(uint8_t *key64, uint8_t *outp_keytable) { // Once again, key is on iclass-format loclass_desdecrypt_iclass(z[0], key64_negated, y[0]); - for (i = 1; i < 8; i++) { + for(i = 1; i < 8; i++) { loclass_rk(key64, i, temp_output); loclass_desdecrypt_iclass(temp_output, z[i - 1], z[i]); loclass_desencrypt_iclass(temp_output, y[i - 1], y[i]); } - if (outp_keytable != NULL) { - for (i = 0 ; i < 8 ; i++) { + if(outp_keytable != NULL) { + for(i = 0; i < 8; i++) { memcpy(outp_keytable + i * 16, y[i], 8); memcpy(outp_keytable + 8 + i * 16, z[i], 8); } diff --git a/lib/loclass/optimized_elite.h b/applications/plugins/picopass/loclass/optimized_elite.h similarity index 95% rename from lib/loclass/optimized_elite.h rename to applications/plugins/picopass/loclass/optimized_elite.h index 9bc30e57..5343ebb0 100644 --- a/lib/loclass/optimized_elite.h +++ b/applications/plugins/picopass/loclass/optimized_elite.h @@ -52,7 +52,7 @@ void loclass_permutekey_rev(const uint8_t key[8], uint8_t dest[8]); * @param csn the CSN used * @param k output */ -void loclass_hash1(const uint8_t *csn, uint8_t *k); -void loclass_hash2(uint8_t *key64, uint8_t *outp_keytable); +void loclass_hash1(const uint8_t* csn, uint8_t* k); +void loclass_hash2(uint8_t* key64, uint8_t* outp_keytable); #endif diff --git a/lib/loclass/optimized_ikeys.c b/applications/plugins/picopass/loclass/optimized_ikeys.c similarity index 90% rename from lib/loclass/optimized_ikeys.c rename to applications/plugins/picopass/loclass/optimized_ikeys.c index 9531c16c..1e6f12c5 100644 --- a/lib/loclass/optimized_ikeys.c +++ b/applications/plugins/picopass/loclass/optimized_ikeys.c @@ -61,13 +61,10 @@ From "Dismantling iclass": #include #include "optimized_cipherutils.h" -static const uint8_t loclass_pi[35] = { - 0x0F, 0x17, 0x1B, 0x1D, 0x1E, 0x27, 0x2B, 0x2D, - 0x2E, 0x33, 0x35, 0x39, 0x36, 0x3A, 0x3C, 0x47, - 0x4B, 0x4D, 0x4E, 0x53, 0x55, 0x56, 0x59, 0x5A, - 0x5C, 0x63, 0x65, 0x66, 0x69, 0x6A, 0x6C, 0x71, - 0x72, 0x74, 0x78 -}; +static const uint8_t loclass_pi[35] = {0x0F, 0x17, 0x1B, 0x1D, 0x1E, 0x27, 0x2B, 0x2D, 0x2E, + 0x33, 0x35, 0x39, 0x36, 0x3A, 0x3C, 0x47, 0x4B, 0x4D, + 0x4E, 0x53, 0x55, 0x56, 0x59, 0x5A, 0x5C, 0x63, 0x65, + 0x66, 0x69, 0x6A, 0x6C, 0x71, 0x72, 0x74, 0x78}; /** * @brief The key diversification algorithm uses 6-bit bytes. @@ -90,7 +87,7 @@ static uint8_t loclass_getSixBitByte(uint64_t c, int n) { * @param z the value to place there * @param n bitnumber. */ -static void loclass_pushbackSixBitByte(uint64_t *c, uint8_t z, int n) { +static void loclass_pushbackSixBitByte(uint64_t* c, uint8_t z, int n) { //0x XXXX YYYY ZZZZ ZZZZ ZZZZ // ^z0 ^z7 //z0: 1111 1100 0000 0000 @@ -106,7 +103,6 @@ static void loclass_pushbackSixBitByte(uint64_t *c, uint8_t z, int n) { eraser = ~eraser; (*c) &= eraser; (*c) |= masked; - } /** * @brief Swaps the z-values. @@ -133,21 +129,21 @@ static uint64_t loclass_swapZvalues(uint64_t c) { * @return 4 six-bit bytes chunked into a uint64_t,as 00..00a0a1a2a3 */ static uint64_t loclass_ck(int i, int j, uint64_t z) { - if (i == 1 && j == -1) { + if(i == 1 && j == -1) { // loclass_ck(1, −1, z [0] . . . z [3] ) = z [0] . . . z [3] return z; - } else if (j == -1) { + } else if(j == -1) { // loclass_ck(i, −1, z [0] . . . z [3] ) = loclass_ck(i − 1, i − 2, z [0] . . . z [3] ) return loclass_ck(i - 1, i - 2, z); } - if (loclass_getSixBitByte(z, i) == loclass_getSixBitByte(z, j)) { + if(loclass_getSixBitByte(z, i) == loclass_getSixBitByte(z, j)) { //loclass_ck(i, j − 1, z [0] . . . z [i] ← j . . . z [3] ) uint64_t newz = 0; int c; - for (c = 0; c < 4; c++) { + for(c = 0; c < 4; c++) { uint8_t val = loclass_getSixBitByte(z, c); - if (c == i) + if(c == i) loclass_pushbackSixBitByte(&newz, j, c); else loclass_pushbackSixBitByte(&newz, val, c); @@ -191,12 +187,16 @@ static uint64_t loclass_check(uint64_t z) { return ck1 | ck2 >> 24; } -static void loclass_permute(LoclassBitstreamIn_t *p_in, uint64_t z, int l, int r, LoclassBitstreamOut_t *out) { - if (loclass_bitsLeft(p_in) == 0) - return; +static void loclass_permute( + LoclassBitstreamIn_t* p_in, + uint64_t z, + int l, + int r, + LoclassBitstreamOut_t* out) { + if(loclass_bitsLeft(p_in) == 0) return; bool pn = loclass_tailBit(p_in); - if (pn) { // pn = 1 + if(pn) { // pn = 1 uint8_t zl = loclass_getSixBitByte(z, l); loclass_push6bits(out, zl + 1); @@ -231,7 +231,7 @@ void loclass_hash0(uint64_t c, uint8_t k[8]) { uint8_t y = (c & 0x00FF000000000000) >> 48; uint64_t zP = 0; - for (int n = 0; n < 4 ; n++) { + for(int n = 0; n < 4; n++) { uint8_t zn = loclass_getSixBitByte(c, n); uint8_t zn4 = loclass_getSixBitByte(c, n + 4); uint8_t _zn = (zn % (63 - n)) + n; @@ -243,10 +243,10 @@ void loclass_hash0(uint64_t c, uint8_t k[8]) { uint64_t zCaret = loclass_check(zP); uint8_t p = loclass_pi[x % 35]; - if (x & 1) //Check if x7 is 1 + if(x & 1) //Check if x7 is 1 p = ~p; - LoclassBitstreamIn_t p_in = { &p, 8, 0 }; + LoclassBitstreamIn_t p_in = {&p, 8, 0}; uint8_t outbuffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; LoclassBitstreamOut_t out = {outbuffer, 0, 0}; loclass_permute(&p_in, zCaret, 0, 4, &out); //returns 48 bits? or 6 8-bytes @@ -259,7 +259,7 @@ void loclass_hash0(uint64_t c, uint8_t k[8]) { zTilde >>= 16; - for (int i = 0; i < 8; i++) { + for(int i = 0; i < 8; i++) { // the key on index i is first a bit from y // then six bits from z, // then a bit from p @@ -270,7 +270,7 @@ void loclass_hash0(uint64_t c, uint8_t k[8]) { //k[i] |= (y << i) & 0x80 ; // First, place y(7-i) leftmost in k - k[i] |= (y << (7 - i)) & 0x80 ; + k[i] |= (y << (7 - i)) & 0x80; uint8_t zTilde_i = loclass_getSixBitByte(zTilde, i); // zTildeI is now on the form 00XXXXXX @@ -285,7 +285,7 @@ void loclass_hash0(uint64_t c, uint8_t k[8]) { //Shift bit i into rightmost location (mask only after complement) uint8_t p_i = p >> i & 0x1; - if (k[i]) { // yi = 1 + if(k[i]) { // yi = 1 k[i] |= ~zTilde_i & 0x7E; k[i] |= p_i & 1; k[i] += 1; @@ -302,7 +302,7 @@ void loclass_hash0(uint64_t c, uint8_t k[8]) { * @param key * @param div_key */ -void loclass_diversifyKey(uint8_t *csn, const uint8_t *key, uint8_t *div_key) { +void loclass_diversifyKey(uint8_t* csn, const uint8_t* key, uint8_t* div_key) { mbedtls_des_context loclass_ctx_enc; // Prepare the DES key @@ -318,4 +318,3 @@ void loclass_diversifyKey(uint8_t *csn, const uint8_t *key, uint8_t *div_key) { loclass_hash0(c_csn, div_key); } - diff --git a/lib/loclass/optimized_ikeys.h b/applications/plugins/picopass/loclass/optimized_ikeys.h similarity index 96% rename from lib/loclass/optimized_ikeys.h rename to applications/plugins/picopass/loclass/optimized_ikeys.h index e960b8be..f2711d31 100644 --- a/lib/loclass/optimized_ikeys.h +++ b/applications/plugins/picopass/loclass/optimized_ikeys.h @@ -56,7 +56,7 @@ void loclass_hash0(uint64_t c, uint8_t k[8]); * @param div_key */ -void loclass_diversifyKey(uint8_t *csn, const uint8_t *key, uint8_t *div_key); +void loclass_diversifyKey(uint8_t* csn, const uint8_t* key, uint8_t* div_key); /** * @brief Permutes a key from standard NIST format to Iclass specific format * @param key diff --git a/applications/picopass/picopass.c b/applications/plugins/picopass/picopass.c similarity index 100% rename from applications/picopass/picopass.c rename to applications/plugins/picopass/picopass.c diff --git a/applications/picopass/picopass.h b/applications/plugins/picopass/picopass.h similarity index 100% rename from applications/picopass/picopass.h rename to applications/plugins/picopass/picopass.h diff --git a/applications/picopass/picopass_device.c b/applications/plugins/picopass/picopass_device.c similarity index 97% rename from applications/picopass/picopass_device.c rename to applications/plugins/picopass/picopass_device.c index 4cd6faaa..e7f3e0be 100644 --- a/applications/picopass/picopass_device.c +++ b/applications/plugins/picopass/picopass_device.c @@ -226,14 +226,13 @@ bool picopass_file_select(PicopassDevice* dev) { // Input events and views are managed by file_browser string_t picopass_app_folder; string_init_set_str(picopass_app_folder, PICOPASS_APP_FOLDER); + + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options(&browser_options, PICOPASS_APP_EXTENSION, &I_Nfc_10px); + bool res = dialog_file_browser_show( - dev->dialogs, - dev->load_path, - picopass_app_folder, - PICOPASS_APP_EXTENSION, - true, - &I_Nfc_10px, - true); + dev->dialogs, dev->load_path, picopass_app_folder, &browser_options); + string_clear(picopass_app_folder); if(res) { string_t filename; @@ -310,10 +309,6 @@ ReturnCode picopass_device_decrypt(uint8_t* enc_data, uint8_t* dec_data) { ReturnCode picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pacs) { ReturnCode err; - // Thank you proxmark! - pacs->legacy = (memcmp(AA1[5].data, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) == 0); - pacs->se_enabled = (memcmp(AA1[5].data, "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0); - pacs->biometrics = AA1[6].data[4]; pacs->pin_length = AA1[6].data[6] & 0x0F; pacs->encryption = AA1[6].data[7]; @@ -348,6 +343,8 @@ ReturnCode picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pa FURI_LOG_D(TAG, "Unknown encryption"); } + pacs->sio = (AA1[10].data[0] == 0x30); // rough check + return ERR_NONE; } diff --git a/applications/picopass/picopass_device.h b/applications/plugins/picopass/picopass_device.h similarity index 95% rename from applications/picopass/picopass_device.h rename to applications/plugins/picopass/picopass_device.h index 0415b879..745b64bd 100644 --- a/applications/picopass/picopass_device.h +++ b/applications/plugins/picopass/picopass_device.h @@ -4,12 +4,11 @@ #include #include #include - -#include - #include -#include -#include + +#include "rfal_picopass.h" +#include "loclass/optimized_ikeys.h" +#include "loclass/optimized_cipher.h" #define PICOPASS_DEV_NAME_MAX_LEN 22 #define PICOPASS_READER_DATA_MAX_SIZE 64 @@ -48,6 +47,7 @@ typedef struct { typedef struct { bool legacy; bool se_enabled; + bool sio; bool biometrics; uint8_t pin_length; PicopassEncryption encryption; diff --git a/applications/picopass/picopass_i.h b/applications/plugins/picopass/picopass_i.h similarity index 96% rename from applications/picopass/picopass_i.h rename to applications/plugins/picopass/picopass_i.h index d295f53a..dec5a865 100644 --- a/applications/picopass/picopass_i.h +++ b/applications/plugins/picopass/picopass_i.h @@ -4,7 +4,7 @@ #include "picopass_worker.h" #include "picopass_device.h" -#include +#include "rfal_picopass.h" #include #include @@ -20,7 +20,7 @@ #include -#include +#include "scenes/picopass_scene.h" #include #include diff --git a/applications/picopass/picopass_worker.c b/applications/plugins/picopass/picopass_worker.c similarity index 77% rename from applications/picopass/picopass_worker.c rename to applications/plugins/picopass/picopass_worker.c index 3ca56d00..532effd9 100644 --- a/applications/picopass/picopass_worker.c +++ b/applications/plugins/picopass/picopass_worker.c @@ -6,14 +6,14 @@ const uint8_t picopass_iclass_key[] = {0xaf, 0xa7, 0x85, 0xa7, 0xda, 0xb3, 0x33, const uint8_t picopass_factory_key[] = {0x76, 0x65, 0x54, 0x43, 0x32, 0x21, 0x10, 0x00}; static void picopass_worker_enable_field() { - st25r3916TxRxOn(); - rfalLowPowerModeStop(); - rfalWorker(); + furi_hal_nfc_ll_txrx_on(); + furi_hal_nfc_exit_sleep(); + furi_hal_nfc_ll_poll(); } static ReturnCode picopass_worker_disable_field(ReturnCode rc) { - st25r3916TxRxOff(); - rfalLowPowerModeStart(); + furi_hal_nfc_ll_txrx_off(); + furi_hal_nfc_start_sleep(); return rc; } @@ -112,18 +112,12 @@ ReturnCode picopass_detect_card(int timeout) { return ERR_NONE; } -ReturnCode picopass_read_card(PicopassBlock* AA1) { +ReturnCode picopass_read_preauth(PicopassBlock* AA1) { rfalPicoPassIdentifyRes idRes; rfalPicoPassSelectRes selRes; - rfalPicoPassReadCheckRes rcRes; - rfalPicoPassCheckRes chkRes; ReturnCode err; - uint8_t div_key[8] = {0}; - uint8_t mac[4] = {0}; - uint8_t ccnr[12] = {0}; - err = rfalPicoPassPollerIdentify(&idRes); if(err != ERR_NONE) { FURI_LOG_E(TAG, "rfalPicoPassPollerIdentify error %d", err); @@ -136,6 +130,62 @@ ReturnCode picopass_read_card(PicopassBlock* AA1) { return err; } + memcpy(AA1[PICOPASS_CSN_BLOCK_INDEX].data, selRes.CSN, sizeof(selRes.CSN)); + FURI_LOG_D( + TAG, + "csn %02x%02x%02x%02x%02x%02x%02x%02x", + AA1[PICOPASS_CSN_BLOCK_INDEX].data[0], + AA1[PICOPASS_CSN_BLOCK_INDEX].data[1], + AA1[PICOPASS_CSN_BLOCK_INDEX].data[2], + AA1[PICOPASS_CSN_BLOCK_INDEX].data[3], + AA1[PICOPASS_CSN_BLOCK_INDEX].data[4], + AA1[PICOPASS_CSN_BLOCK_INDEX].data[5], + AA1[PICOPASS_CSN_BLOCK_INDEX].data[6], + AA1[PICOPASS_CSN_BLOCK_INDEX].data[7]); + + rfalPicoPassReadBlockRes cfg = {0}; + err = rfalPicoPassPollerReadBlock(PICOPASS_CONFIG_BLOCK_INDEX, &cfg); + memcpy(AA1[PICOPASS_CONFIG_BLOCK_INDEX].data, cfg.data, sizeof(cfg.data)); + FURI_LOG_D( + TAG, + "config %02x%02x%02x%02x%02x%02x%02x%02x", + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0], + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[1], + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[2], + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[3], + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[4], + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[5], + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[6], + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[7]); + + rfalPicoPassReadBlockRes aia; + err = rfalPicoPassPollerReadBlock(PICOPASS_AIA_BLOCK_INDEX, &aia); + memcpy(AA1[PICOPASS_AIA_BLOCK_INDEX].data, aia.data, sizeof(aia.data)); + FURI_LOG_D( + TAG, + "aia %02x%02x%02x%02x%02x%02x%02x%02x", + AA1[PICOPASS_AIA_BLOCK_INDEX].data[0], + AA1[PICOPASS_AIA_BLOCK_INDEX].data[1], + AA1[PICOPASS_AIA_BLOCK_INDEX].data[2], + AA1[PICOPASS_AIA_BLOCK_INDEX].data[3], + AA1[PICOPASS_AIA_BLOCK_INDEX].data[4], + AA1[PICOPASS_AIA_BLOCK_INDEX].data[5], + AA1[PICOPASS_AIA_BLOCK_INDEX].data[6], + AA1[PICOPASS_AIA_BLOCK_INDEX].data[7]); + + return ERR_NONE; +} + +ReturnCode picopass_read_card(PicopassBlock* AA1) { + rfalPicoPassReadCheckRes rcRes; + rfalPicoPassCheckRes chkRes; + + ReturnCode err; + + uint8_t div_key[8] = {0}; + uint8_t mac[4] = {0}; + uint8_t ccnr[12] = {0}; + err = rfalPicoPassPollerReadCheck(&rcRes); if(err != ERR_NONE) { FURI_LOG_E(TAG, "rfalPicoPassPollerReadCheck error %d", err); @@ -143,7 +193,7 @@ ReturnCode picopass_read_card(PicopassBlock* AA1) { } memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0 - loclass_diversifyKey(selRes.CSN, picopass_iclass_key, div_key); + loclass_diversifyKey(AA1[PICOPASS_CSN_BLOCK_INDEX].data, picopass_iclass_key, div_key); loclass_opt_doReaderMAC(ccnr, div_key, mac); err = rfalPicoPassPollerCheck(mac, &chkRes); @@ -152,18 +202,11 @@ ReturnCode picopass_read_card(PicopassBlock* AA1) { return err; } - rfalPicoPassReadBlockRes csn; - err = rfalPicoPassPollerReadBlock(PICOPASS_CSN_BLOCK_INDEX, &csn); - memcpy(AA1[PICOPASS_CSN_BLOCK_INDEX].data, csn.data, sizeof(csn.data)); - - rfalPicoPassReadBlockRes cfg; - err = rfalPicoPassPollerReadBlock(PICOPASS_CONFIG_BLOCK_INDEX, &cfg); - memcpy(AA1[PICOPASS_CONFIG_BLOCK_INDEX].data, cfg.data, sizeof(cfg.data)); - - size_t app_limit = cfg.data[0] < PICOPASS_MAX_APP_LIMIT ? cfg.data[0] : PICOPASS_MAX_APP_LIMIT; + size_t app_limit = AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0] < PICOPASS_MAX_APP_LIMIT ? + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0] : + PICOPASS_MAX_APP_LIMIT; for(size_t i = 2; i < app_limit; i++) { - FURI_LOG_D(TAG, "rfalPicoPassPollerReadBlock block %d", i); rfalPicoPassReadBlockRes block; err = rfalPicoPassPollerReadBlock(i, &block); if(err != ERR_NONE) { @@ -287,11 +330,30 @@ void picopass_worker_detect(PicopassWorker* picopass_worker) { PicopassPacs* pacs = &dev_data->pacs; ReturnCode err; + // reset device data + for(size_t i = 0; i < PICOPASS_MAX_APP_LIMIT; i++) { + memset(AA1[i].data, 0, sizeof(AA1[i].data)); + } + memset(pacs, 0, sizeof(PicopassPacs)); + PicopassWorkerEvent nextState = PicopassWorkerEventSuccess; while(picopass_worker->state == PicopassWorkerStateDetect) { if(picopass_detect_card(1000) == ERR_NONE) { // Process first found device + err = picopass_read_preauth(AA1); + if(err != ERR_NONE) { + FURI_LOG_E(TAG, "picopass_read_preauth error %d", err); + nextState = PicopassWorkerEventFail; + } + + // Thank you proxmark! + pacs->legacy = (memcmp(AA1[5].data, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) == 0); + pacs->se_enabled = (memcmp(AA1[5].data, "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0); + if(pacs->se_enabled) { + FURI_LOG_D(TAG, "SE enabled"); + } + err = picopass_read_card(AA1); if(err != ERR_NONE) { FURI_LOG_E(TAG, "picopass_read_card error %d", err); diff --git a/applications/picopass/picopass_worker.h b/applications/plugins/picopass/picopass_worker.h similarity index 97% rename from applications/picopass/picopass_worker.h rename to applications/plugins/picopass/picopass_worker.h index 6ad70905..29a890a1 100644 --- a/applications/picopass/picopass_worker.h +++ b/applications/plugins/picopass/picopass_worker.h @@ -24,6 +24,7 @@ typedef enum { PicopassWorkerEventSuccess, PicopassWorkerEventFail, PicopassWorkerEventNoCardDetected, + PicopassWorkerEventSeEnabled, PicopassWorkerEventStartReading, } PicopassWorkerEvent; diff --git a/applications/picopass/picopass_worker_i.h b/applications/plugins/picopass/picopass_worker_i.h similarity index 100% rename from applications/picopass/picopass_worker_i.h rename to applications/plugins/picopass/picopass_worker_i.h diff --git a/lib/ST25RFAL002/source/rfal_picopass.c b/applications/plugins/picopass/rfal_picopass.c similarity index 50% rename from lib/ST25RFAL002/source/rfal_picopass.c rename to applications/plugins/picopass/rfal_picopass.c index f33fcdf8..50cd4e95 100644 --- a/lib/ST25RFAL002/source/rfal_picopass.c +++ b/applications/plugins/picopass/rfal_picopass.c @@ -1,7 +1,10 @@ - #include "rfal_picopass.h" #include "utils.h" +#define RFAL_PICOPASS_TXRX_FLAGS \ + (FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | \ + FURI_HAL_NFC_LL_TXRX_FLAGS_PAR_RX_REMV | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP) + #define TAG "RFAL_PICOPASS" typedef struct { @@ -15,40 +18,68 @@ typedef struct { uint8_t mac[4]; } rfalPicoPassCheckReq; -ReturnCode rfalPicoPassPollerInitialize(void) { - ReturnCode ret; +static uint16_t rfalPicoPassUpdateCcitt(uint16_t crcSeed, uint8_t dataByte) { + uint16_t crc = crcSeed; + uint8_t dat = dataByte; - EXIT_ON_ERR(ret, rfalSetMode(RFAL_MODE_POLL_PICOPASS, RFAL_BR_26p48, RFAL_BR_26p48)); - rfalSetErrorHandling(RFAL_ERRORHANDLING_NFC); + dat ^= (uint8_t)(crc & 0xFFU); + dat ^= (dat << 4); - rfalSetGT(RFAL_GT_PICOPASS); - rfalSetFDTListen(RFAL_FDT_LISTEN_PICOPASS_POLLER); - rfalSetFDTPoll(RFAL_FDT_POLL_PICOPASS_POLLER); + crc = (crc >> 8) ^ (((uint16_t)dat) << 8) ^ (((uint16_t)dat) << 3) ^ (((uint16_t)dat) >> 4); - return ERR_NONE; + return crc; } -ReturnCode rfalPicoPassPollerCheckPresence(void) { - ReturnCode ret; +static uint16_t + rfalPicoPassCalculateCcitt(uint16_t preloadValue, const uint8_t* buf, uint16_t length) { + uint16_t crc = preloadValue; + uint16_t index; + + for(index = 0; index < length; index++) { + crc = rfalPicoPassUpdateCcitt(crc, buf[index]); + } + + return crc; +} + +FuriHalNfcReturn rfalPicoPassPollerInitialize(void) { + FuriHalNfcReturn ret; + + ret = furi_hal_nfc_ll_set_mode( + FuriHalNfcModePollPicopass, FuriHalNfcBitrate26p48, FuriHalNfcBitrate26p48); + if(ret != FuriHalNfcReturnOk) { + return ret; + }; + + furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); + furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_PICOPASS); + furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_PICOPASS_POLLER); + furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_PICOPASS_POLLER); + + return FuriHalNfcReturnOk; +} + +FuriHalNfcReturn rfalPicoPassPollerCheckPresence(void) { + FuriHalNfcReturn ret; uint8_t txBuf[1] = {RFAL_PICOPASS_CMD_ACTALL}; uint8_t rxBuf[32] = {0}; uint16_t recvLen = 0; uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; - uint32_t fwt = rfalConvMsTo1fc(20); + uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); - ret = rfalTransceiveBlockingTxRx(txBuf, 1, rxBuf, 32, &recvLen, flags, fwt); + ret = furi_hal_nfc_ll_txrx(txBuf, 1, rxBuf, 32, &recvLen, flags, fwt); return ret; } -ReturnCode rfalPicoPassPollerIdentify(rfalPicoPassIdentifyRes* idRes) { - ReturnCode ret; +FuriHalNfcReturn rfalPicoPassPollerIdentify(rfalPicoPassIdentifyRes* idRes) { + FuriHalNfcReturn ret; uint8_t txBuf[1] = {RFAL_PICOPASS_CMD_IDENTIFY}; uint16_t recvLen = 0; uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; - uint32_t fwt = rfalConvMsTo1fc(20); + uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); - ret = rfalTransceiveBlockingTxRx( + ret = furi_hal_nfc_ll_txrx( txBuf, sizeof(txBuf), (uint8_t*)idRes, @@ -61,17 +92,17 @@ ReturnCode rfalPicoPassPollerIdentify(rfalPicoPassIdentifyRes* idRes) { return ret; } -ReturnCode rfalPicoPassPollerSelect(uint8_t* csn, rfalPicoPassSelectRes* selRes) { - ReturnCode ret; +FuriHalNfcReturn rfalPicoPassPollerSelect(uint8_t* csn, rfalPicoPassSelectRes* selRes) { + FuriHalNfcReturn ret; rfalPicoPassSelectReq selReq; selReq.CMD = RFAL_PICOPASS_CMD_SELECT; ST_MEMCPY(selReq.CSN, csn, RFAL_PICOPASS_UID_LEN); uint16_t recvLen = 0; uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; - uint32_t fwt = rfalConvMsTo1fc(20); + uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); - ret = rfalTransceiveBlockingTxRx( + ret = furi_hal_nfc_ll_txrx( (uint8_t*)&selReq, sizeof(rfalPicoPassSelectReq), (uint8_t*)selRes, @@ -80,21 +111,21 @@ ReturnCode rfalPicoPassPollerSelect(uint8_t* csn, rfalPicoPassSelectRes* selRes) flags, fwt); // printf("select rx: %d %s\n", recvLen, hex2Str(selRes->CSN, RFAL_PICOPASS_UID_LEN)); - if(ret == ERR_TIMEOUT) { - return ERR_NONE; + if(ret == FuriHalNfcReturnTimeout) { + return FuriHalNfcReturnOk; } return ret; } -ReturnCode rfalPicoPassPollerReadCheck(rfalPicoPassReadCheckRes* rcRes) { - ReturnCode ret; +FuriHalNfcReturn rfalPicoPassPollerReadCheck(rfalPicoPassReadCheckRes* rcRes) { + FuriHalNfcReturn ret; uint8_t txBuf[2] = {RFAL_PICOPASS_CMD_READCHECK, 0x02}; uint16_t recvLen = 0; uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; - uint32_t fwt = rfalConvMsTo1fc(20); + uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); - ret = rfalTransceiveBlockingTxRx( + ret = furi_hal_nfc_ll_txrx( txBuf, sizeof(txBuf), (uint8_t*)rcRes, @@ -104,25 +135,25 @@ ReturnCode rfalPicoPassPollerReadCheck(rfalPicoPassReadCheckRes* rcRes) { fwt); // printf("readcheck rx: %d %s\n", recvLen, hex2Str(rcRes->CCNR, 8)); - if(ret == ERR_CRC) { - return ERR_NONE; + if(ret == FuriHalNfcReturnCrc) { + return FuriHalNfcReturnOk; } return ret; } -ReturnCode rfalPicoPassPollerCheck(uint8_t* mac, rfalPicoPassCheckRes* chkRes) { - ReturnCode ret; +FuriHalNfcReturn rfalPicoPassPollerCheck(uint8_t* mac, rfalPicoPassCheckRes* chkRes) { + FuriHalNfcReturn ret; rfalPicoPassCheckReq chkReq; chkReq.CMD = RFAL_PICOPASS_CMD_CHECK; ST_MEMCPY(chkReq.mac, mac, 4); ST_MEMSET(chkReq.null, 0, 4); uint16_t recvLen = 0; uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; - uint32_t fwt = rfalConvMsTo1fc(20); + uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); // printf("check tx: %s\n", hex2Str((uint8_t *)&chkReq, sizeof(rfalPicoPassCheckReq))); - ret = rfalTransceiveBlockingTxRx( + ret = furi_hal_nfc_ll_txrx( (uint8_t*)&chkReq, sizeof(rfalPicoPassCheckReq), (uint8_t*)chkRes, @@ -131,26 +162,26 @@ ReturnCode rfalPicoPassPollerCheck(uint8_t* mac, rfalPicoPassCheckRes* chkRes) { flags, fwt); // printf("check rx: %d %s\n", recvLen, hex2Str(chkRes->mac, 4)); - if(ret == ERR_CRC) { - return ERR_NONE; + if(ret == FuriHalNfcReturnCrc) { + return FuriHalNfcReturnOk; } return ret; } -ReturnCode rfalPicoPassPollerReadBlock(uint8_t blockNum, rfalPicoPassReadBlockRes* readRes) { - ReturnCode ret; +FuriHalNfcReturn rfalPicoPassPollerReadBlock(uint8_t blockNum, rfalPicoPassReadBlockRes* readRes) { + FuriHalNfcReturn ret; uint8_t txBuf[4] = {RFAL_PICOPASS_CMD_READ, 0, 0, 0}; txBuf[1] = blockNum; - uint16_t crc = rfalCrcCalculateCcitt(0xE012, txBuf + 1, 1); + uint16_t crc = rfalPicoPassCalculateCcitt(0xE012, txBuf + 1, 1); memcpy(txBuf + 2, &crc, sizeof(uint16_t)); uint16_t recvLen = 0; uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; - uint32_t fwt = rfalConvMsTo1fc(20); + uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); - ret = rfalTransceiveBlockingTxRx( + ret = furi_hal_nfc_ll_txrx( txBuf, sizeof(txBuf), (uint8_t*)readRes, @@ -161,8 +192,8 @@ ReturnCode rfalPicoPassPollerReadBlock(uint8_t blockNum, rfalPicoPassReadBlockRe return ret; } -ReturnCode rfalPicoPassPollerWriteBlock(uint8_t blockNum, uint8_t data[8], uint8_t mac[4]) { - ReturnCode ret; +FuriHalNfcReturn rfalPicoPassPollerWriteBlock(uint8_t blockNum, uint8_t data[8], uint8_t mac[4]) { + FuriHalNfcReturn ret; uint8_t txBuf[14] = {RFAL_PICOPASS_CMD_WRITE, blockNum, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; memcpy(txBuf + 2, data, RFAL_PICOPASS_MAX_BLOCK_LEN); @@ -170,13 +201,13 @@ ReturnCode rfalPicoPassPollerWriteBlock(uint8_t blockNum, uint8_t data[8], uint8 uint16_t recvLen = 0; uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; - uint32_t fwt = rfalConvMsTo1fc(20); + uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); rfalPicoPassReadBlockRes block; - ret = rfalTransceiveBlockingTxRx( + ret = furi_hal_nfc_ll_txrx( txBuf, sizeof(txBuf), (uint8_t*)&block, sizeof(block), &recvLen, flags, fwt); - if(ret == ERR_NONE) { + if(ret == FuriHalNfcReturnOk) { // TODO: compare response } diff --git a/applications/plugins/picopass/rfal_picopass.h b/applications/plugins/picopass/rfal_picopass.h new file mode 100644 index 00000000..6926b2a7 --- /dev/null +++ b/applications/plugins/picopass/rfal_picopass.h @@ -0,0 +1,48 @@ +#pragma once + +#include + +#define RFAL_PICOPASS_UID_LEN 8 +#define RFAL_PICOPASS_MAX_BLOCK_LEN 8 + +enum { + RFAL_PICOPASS_CMD_ACTALL = 0x0A, + RFAL_PICOPASS_CMD_IDENTIFY = 0x0C, + RFAL_PICOPASS_CMD_SELECT = 0x81, + RFAL_PICOPASS_CMD_READCHECK = 0x88, + RFAL_PICOPASS_CMD_CHECK = 0x05, + RFAL_PICOPASS_CMD_READ = 0x0C, + RFAL_PICOPASS_CMD_WRITE = 0x87, +}; + +typedef struct { + uint8_t CSN[RFAL_PICOPASS_UID_LEN]; // Anti-collision CSN + uint8_t crc[2]; +} rfalPicoPassIdentifyRes; + +typedef struct { + uint8_t CSN[RFAL_PICOPASS_UID_LEN]; // Real CSN + uint8_t crc[2]; +} rfalPicoPassSelectRes; + +typedef struct { + uint8_t CCNR[8]; +} rfalPicoPassReadCheckRes; + +typedef struct { + uint8_t mac[4]; +} rfalPicoPassCheckRes; + +typedef struct { + uint8_t data[RFAL_PICOPASS_MAX_BLOCK_LEN]; + uint8_t crc[2]; +} rfalPicoPassReadBlockRes; + +FuriHalNfcReturn rfalPicoPassPollerInitialize(void); +FuriHalNfcReturn rfalPicoPassPollerCheckPresence(void); +FuriHalNfcReturn rfalPicoPassPollerIdentify(rfalPicoPassIdentifyRes* idRes); +FuriHalNfcReturn rfalPicoPassPollerSelect(uint8_t* csn, rfalPicoPassSelectRes* selRes); +FuriHalNfcReturn rfalPicoPassPollerReadCheck(rfalPicoPassReadCheckRes* rcRes); +FuriHalNfcReturn rfalPicoPassPollerCheck(uint8_t* mac, rfalPicoPassCheckRes* chkRes); +FuriHalNfcReturn rfalPicoPassPollerReadBlock(uint8_t blockNum, rfalPicoPassReadBlockRes* readRes); +FuriHalNfcReturn rfalPicoPassPollerWriteBlock(uint8_t blockNum, uint8_t data[8], uint8_t mac[4]); diff --git a/applications/picopass/scenes/picopass_scene.c b/applications/plugins/picopass/scenes/picopass_scene.c similarity index 100% rename from applications/picopass/scenes/picopass_scene.c rename to applications/plugins/picopass/scenes/picopass_scene.c diff --git a/applications/picopass/scenes/picopass_scene.h b/applications/plugins/picopass/scenes/picopass_scene.h similarity index 100% rename from applications/picopass/scenes/picopass_scene.h rename to applications/plugins/picopass/scenes/picopass_scene.h diff --git a/applications/picopass/scenes/picopass_scene_card_menu.c b/applications/plugins/picopass/scenes/picopass_scene_card_menu.c similarity index 100% rename from applications/picopass/scenes/picopass_scene_card_menu.c rename to applications/plugins/picopass/scenes/picopass_scene_card_menu.c diff --git a/applications/picopass/scenes/picopass_scene_config.h b/applications/plugins/picopass/scenes/picopass_scene_config.h similarity index 100% rename from applications/picopass/scenes/picopass_scene_config.h rename to applications/plugins/picopass/scenes/picopass_scene_config.h diff --git a/applications/picopass/scenes/picopass_scene_delete.c b/applications/plugins/picopass/scenes/picopass_scene_delete.c similarity index 100% rename from applications/picopass/scenes/picopass_scene_delete.c rename to applications/plugins/picopass/scenes/picopass_scene_delete.c diff --git a/applications/picopass/scenes/picopass_scene_delete_success.c b/applications/plugins/picopass/scenes/picopass_scene_delete_success.c similarity index 100% rename from applications/picopass/scenes/picopass_scene_delete_success.c rename to applications/plugins/picopass/scenes/picopass_scene_delete_success.c diff --git a/applications/picopass/scenes/picopass_scene_device_info.c b/applications/plugins/picopass/scenes/picopass_scene_device_info.c similarity index 100% rename from applications/picopass/scenes/picopass_scene_device_info.c rename to applications/plugins/picopass/scenes/picopass_scene_device_info.c diff --git a/applications/picopass/scenes/picopass_scene_file_select.c b/applications/plugins/picopass/scenes/picopass_scene_file_select.c similarity index 95% rename from applications/picopass/scenes/picopass_scene_file_select.c rename to applications/plugins/picopass/scenes/picopass_scene_file_select.c index b3d4c3d7..2fc64746 100644 --- a/applications/picopass/scenes/picopass_scene_file_select.c +++ b/applications/plugins/picopass/scenes/picopass_scene_file_select.c @@ -1,5 +1,5 @@ #include "../picopass_i.h" -#include "picopass/picopass_device.h" +#include "../picopass_device.h" void picopass_scene_file_select_on_enter(void* context) { Picopass* picopass = context; diff --git a/applications/picopass/scenes/picopass_scene_read_card.c b/applications/plugins/picopass/scenes/picopass_scene_read_card.c similarity index 100% rename from applications/picopass/scenes/picopass_scene_read_card.c rename to applications/plugins/picopass/scenes/picopass_scene_read_card.c diff --git a/applications/picopass/scenes/picopass_scene_read_card_success.c b/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c similarity index 82% rename from applications/picopass/scenes/picopass_scene_read_card_success.c rename to applications/plugins/picopass/scenes/picopass_scene_read_card_success.c index c281b32c..785f3a7d 100644 --- a/applications/picopass/scenes/picopass_scene_read_card_success.c +++ b/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c @@ -17,8 +17,10 @@ void picopass_scene_read_card_success_on_enter(void* context) { Picopass* picopass = context; string_t credential_str; string_t wiegand_str; + string_t sio_str; string_init(credential_str); string_init(wiegand_str); + string_init(sio_str); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); @@ -32,6 +34,10 @@ void picopass_scene_read_card_success_on_enter(void* context) { if(pacs->record.bitLength == 0) { string_cat_printf(wiegand_str, "Read Failed"); + if(pacs->se_enabled) { + string_cat_printf(credential_str, "SE enabled"); + } + widget_add_button_element( widget, GuiButtonTypeLeft, @@ -39,8 +45,6 @@ void picopass_scene_read_card_success_on_enter(void* context) { picopass_scene_read_card_success_widget_callback, picopass); - widget_add_string_element( - widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, string_get_cstr(wiegand_str)); } else { size_t bytesLength = 1 + pacs->record.bitLength / 8; string_set_str(credential_str, ""); @@ -55,6 +59,10 @@ void picopass_scene_read_card_success_on_enter(void* context) { string_cat_printf(wiegand_str, "%d bits", pacs->record.bitLength); } + if(pacs->sio) { + string_cat_printf(sio_str, "+SIO"); + } + widget_add_button_element( widget, GuiButtonTypeLeft, @@ -68,20 +76,18 @@ void picopass_scene_read_card_success_on_enter(void* context) { "More", picopass_scene_read_card_success_widget_callback, picopass); - - widget_add_string_element( - widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, string_get_cstr(wiegand_str)); - widget_add_string_element( - widget, - 64, - 32, - AlignCenter, - AlignCenter, - FontSecondary, - string_get_cstr(credential_str)); } + + widget_add_string_element( + widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, string_get_cstr(wiegand_str)); + widget_add_string_element( + widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(credential_str)); + widget_add_string_element( + widget, 64, 42, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(sio_str)); + string_clear(credential_str); string_clear(wiegand_str); + string_clear(sio_str); view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget); } diff --git a/applications/picopass/scenes/picopass_scene_save_name.c b/applications/plugins/picopass/scenes/picopass_scene_save_name.c similarity index 100% rename from applications/picopass/scenes/picopass_scene_save_name.c rename to applications/plugins/picopass/scenes/picopass_scene_save_name.c diff --git a/applications/picopass/scenes/picopass_scene_save_success.c b/applications/plugins/picopass/scenes/picopass_scene_save_success.c similarity index 100% rename from applications/picopass/scenes/picopass_scene_save_success.c rename to applications/plugins/picopass/scenes/picopass_scene_save_success.c diff --git a/applications/picopass/scenes/picopass_scene_saved_menu.c b/applications/plugins/picopass/scenes/picopass_scene_saved_menu.c similarity index 100% rename from applications/picopass/scenes/picopass_scene_saved_menu.c rename to applications/plugins/picopass/scenes/picopass_scene_saved_menu.c diff --git a/applications/picopass/scenes/picopass_scene_start.c b/applications/plugins/picopass/scenes/picopass_scene_start.c similarity index 100% rename from applications/picopass/scenes/picopass_scene_start.c rename to applications/plugins/picopass/scenes/picopass_scene_start.c diff --git a/applications/picopass/scenes/picopass_scene_write_card.c b/applications/plugins/picopass/scenes/picopass_scene_write_card.c similarity index 100% rename from applications/picopass/scenes/picopass_scene_write_card.c rename to applications/plugins/picopass/scenes/picopass_scene_write_card.c diff --git a/applications/picopass/scenes/picopass_scene_write_card_success.c b/applications/plugins/picopass/scenes/picopass_scene_write_card_success.c similarity index 100% rename from applications/picopass/scenes/picopass_scene_write_card_success.c rename to applications/plugins/picopass/scenes/picopass_scene_write_card_success.c diff --git a/applications/snake_game/application.fam b/applications/plugins/snake_game/application.fam similarity index 79% rename from applications/snake_game/application.fam rename to applications/plugins/snake_game/application.fam index 5d6ad527..d55f53bb 100644 --- a/applications/snake_game/application.fam +++ b/applications/plugins/snake_game/application.fam @@ -6,6 +6,7 @@ App( cdefines=["APP_SNAKE_GAME"], requires=["gui"], stack_size=1 * 1024, - icon="A_Plugins_14", order=30, + fap_icon="snake_10px.png", + fap_category="Games", ) diff --git a/applications/plugins/snake_game/snake_10px.png b/applications/plugins/snake_game/snake_10px.png new file mode 100644 index 00000000..52d9fa7e Binary files /dev/null and b/applications/plugins/snake_game/snake_10px.png differ diff --git a/applications/snake_game/snake_game.c b/applications/plugins/snake_game/snake_game.c similarity index 100% rename from applications/snake_game/snake_game.c rename to applications/plugins/snake_game/snake_game.c diff --git a/applications/power/application.fam b/applications/power/application.fam deleted file mode 100644 index 1e503749..00000000 --- a/applications/power/application.fam +++ /dev/null @@ -1,53 +0,0 @@ -App( - appid="power", - name="PowerSrv", - apptype=FlipperAppType.SERVICE, - entry_point="power_srv", - cdefines=["SRV_POWER"], - requires=[ - "gui", - "cli", - ], - provides=[ - "power_settings", - "power_start", - ], - stack_size=1 * 1024, - order=110, -) - -App( - appid="power_settings", - name="Power", - apptype=FlipperAppType.SETTINGS, - entry_point="power_settings_app", - requires=[ - "gui", - "power", - ], - flags=["InsomniaSafe"], - stack_size=1 * 1024, - order=40, -) - -App( - appid="power_start", - apptype=FlipperAppType.STARTUP, - entry_point="power_on_system_start", - requires=["power"], - order=80, -) - -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, -) diff --git a/applications/power/power_cli.h b/applications/power/power_cli.h deleted file mode 100644 index ef55d869..00000000 --- a/applications/power/power_cli.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -void power_on_system_start(); diff --git a/applications/services/application.fam b/applications/services/application.fam new file mode 100644 index 00000000..aec49b23 --- /dev/null +++ b/applications/services/application.fam @@ -0,0 +1,13 @@ +App( + appid="basic_services", + name="Basic services", + apptype=FlipperAppType.METAPACKAGE, + provides=[ + "crypto_start", + "rpc_start", + "bt", + "desktop", + "loader", + "power", + ], +) diff --git a/applications/applications.h b/applications/services/applications.h similarity index 100% rename from applications/applications.h rename to applications/services/applications.h diff --git a/applications/services/bt/application.fam b/applications/services/bt/application.fam new file mode 100644 index 00000000..2e97dc1d --- /dev/null +++ b/applications/services/bt/application.fam @@ -0,0 +1,25 @@ +App( + appid="bt", + name="BtSrv", + apptype=FlipperAppType.SERVICE, + entry_point="bt_srv", + cdefines=["SRV_BT"], + requires=[ + "cli", + "dialogs", + ], + provides=[ + "bt_start", + "bt_settings", + ], + stack_size=1 * 1024, + order=20, + sdk_headers=["bt_service/bt.h"], +) + +App( + appid="bt_start", + apptype=FlipperAppType.STARTUP, + entry_point="bt_on_system_start", + order=70, +) diff --git a/applications/bt/bt_cli.c b/applications/services/bt/bt_cli.c similarity index 99% rename from applications/bt/bt_cli.c rename to applications/services/bt/bt_cli.c index 79500fac..ff5ebb44 100644 --- a/applications/bt/bt_cli.c +++ b/applications/services/bt/bt_cli.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include diff --git a/applications/bt/bt_service/bt.c b/applications/services/bt/bt_service/bt.c similarity index 100% rename from applications/bt/bt_service/bt.c rename to applications/services/bt/bt_service/bt.c diff --git a/applications/bt/bt_service/bt.h b/applications/services/bt/bt_service/bt.h similarity index 100% rename from applications/bt/bt_service/bt.h rename to applications/services/bt/bt_service/bt.h diff --git a/applications/bt/bt_service/bt_api.c b/applications/services/bt/bt_service/bt_api.c similarity index 100% rename from applications/bt/bt_service/bt_api.c rename to applications/services/bt/bt_service/bt_api.c diff --git a/applications/bt/bt_service/bt_i.h b/applications/services/bt/bt_service/bt_i.h similarity index 92% rename from applications/bt/bt_service/bt_i.h rename to applications/services/bt/bt_service/bt_i.h index a45a36c9..5769243e 100644 --- a/applications/bt/bt_service/bt_i.h +++ b/applications/services/bt/bt_service/bt_i.h @@ -11,10 +11,10 @@ #include #include -#include -#include +#include +#include -#include "../bt_settings.h" +#include #define BT_API_UNLOCK_EVENT (1UL << 0) diff --git a/applications/bt/bt_service/bt_keys_filename.h b/applications/services/bt/bt_service/bt_keys_filename.h similarity index 100% rename from applications/bt/bt_service/bt_keys_filename.h rename to applications/services/bt/bt_service/bt_keys_filename.h diff --git a/applications/bt/bt_service/bt_keys_storage.c b/applications/services/bt/bt_service/bt_keys_storage.c similarity index 100% rename from applications/bt/bt_service/bt_keys_storage.c rename to applications/services/bt/bt_service/bt_keys_storage.c diff --git a/applications/bt/bt_service/bt_keys_storage.h b/applications/services/bt/bt_service/bt_keys_storage.h similarity index 100% rename from applications/bt/bt_service/bt_keys_storage.h rename to applications/services/bt/bt_service/bt_keys_storage.h diff --git a/applications/bt/bt_settings.c b/applications/services/bt/bt_settings.c similarity index 100% rename from applications/bt/bt_settings.c rename to applications/services/bt/bt_settings.c diff --git a/applications/bt/bt_settings.h b/applications/services/bt/bt_settings.h similarity index 100% rename from applications/bt/bt_settings.h rename to applications/services/bt/bt_settings.h diff --git a/applications/bt/bt_settings_filename.h b/applications/services/bt/bt_settings_filename.h similarity index 100% rename from applications/bt/bt_settings_filename.h rename to applications/services/bt/bt_settings_filename.h diff --git a/applications/cli/application.fam b/applications/services/cli/application.fam similarity index 81% rename from applications/cli/application.fam rename to applications/services/cli/application.fam index 73c70aa4..7a57bb60 100644 --- a/applications/cli/application.fam +++ b/applications/services/cli/application.fam @@ -6,4 +6,5 @@ App( cdefines=["SRV_CLI"], stack_size=4 * 1024, order=30, + sdk_headers=["cli.h", "cli_vcp.h"], ) diff --git a/applications/cli/cli.c b/applications/services/cli/cli.c similarity index 100% rename from applications/cli/cli.c rename to applications/services/cli/cli.c diff --git a/applications/cli/cli.h b/applications/services/cli/cli.h similarity index 100% rename from applications/cli/cli.h rename to applications/services/cli/cli.h diff --git a/applications/cli/cli_command_gpio.c b/applications/services/cli/cli_command_gpio.c similarity index 100% rename from applications/cli/cli_command_gpio.c rename to applications/services/cli/cli_command_gpio.c diff --git a/applications/cli/cli_command_gpio.h b/applications/services/cli/cli_command_gpio.h similarity index 100% rename from applications/cli/cli_command_gpio.h rename to applications/services/cli/cli_command_gpio.h diff --git a/applications/cli/cli_commands.c b/applications/services/cli/cli_commands.c similarity index 100% rename from applications/cli/cli_commands.c rename to applications/services/cli/cli_commands.c diff --git a/applications/cli/cli_commands.h b/applications/services/cli/cli_commands.h similarity index 100% rename from applications/cli/cli_commands.h rename to applications/services/cli/cli_commands.h diff --git a/applications/cli/cli_i.h b/applications/services/cli/cli_i.h similarity index 92% rename from applications/cli/cli_i.h rename to applications/services/cli/cli_i.h index 8f0bd85d..ba4582d0 100644 --- a/applications/cli/cli_i.h +++ b/applications/services/cli/cli_i.h @@ -9,17 +9,21 @@ #include #include +#include "cli_vcp.h" + #define CLI_LINE_SIZE_MAX #define CLI_COMMANDS_TREE_RANK 4 +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { CliCallback callback; void* context; uint32_t flags; } CliCommand; -typedef struct CliSession CliSession; - struct CliSession { void (*init)(void); void (*deinit)(void); @@ -57,3 +61,7 @@ void cli_reset(Cli* cli); void cli_putc(Cli* cli, char c); void cli_stdout_callback(void* _cookie, const char* data, size_t size); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/applications/cli/cli_vcp.c b/applications/services/cli/cli_vcp.c similarity index 99% rename from applications/cli/cli_vcp.c rename to applications/services/cli/cli_vcp.c index 5a8b44dc..f2893a48 100644 --- a/applications/cli/cli_vcp.c +++ b/applications/services/cli/cli_vcp.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/applications/cli/cli_vcp.h b/applications/services/cli/cli_vcp.h similarity index 80% rename from applications/cli/cli_vcp.h rename to applications/services/cli/cli_vcp.h index 2bd47efb..3aef2ef7 100644 --- a/applications/cli/cli_vcp.h +++ b/applications/services/cli/cli_vcp.h @@ -5,12 +5,12 @@ #pragma once -#include "cli_i.h" - #ifdef __cplusplus extern "C" { #endif +typedef struct CliSession CliSession; + extern CliSession cli_vcp; #ifdef __cplusplus diff --git a/applications/crypto/application.fam b/applications/services/crypto/application.fam similarity index 100% rename from applications/crypto/application.fam rename to applications/services/crypto/application.fam diff --git a/applications/crypto/crypto_cli.c b/applications/services/crypto/crypto_cli.c similarity index 100% rename from applications/crypto/crypto_cli.c rename to applications/services/crypto/crypto_cli.c diff --git a/applications/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c similarity index 100% rename from applications/desktop/animations/animation_manager.c rename to applications/services/desktop/animations/animation_manager.c diff --git a/applications/desktop/animations/animation_manager.h b/applications/services/desktop/animations/animation_manager.h similarity index 100% rename from applications/desktop/animations/animation_manager.h rename to applications/services/desktop/animations/animation_manager.h diff --git a/applications/desktop/animations/animation_storage.c b/applications/services/desktop/animations/animation_storage.c similarity index 100% rename from applications/desktop/animations/animation_storage.c rename to applications/services/desktop/animations/animation_storage.c diff --git a/applications/desktop/animations/animation_storage.h b/applications/services/desktop/animations/animation_storage.h similarity index 100% rename from applications/desktop/animations/animation_storage.h rename to applications/services/desktop/animations/animation_storage.h diff --git a/applications/desktop/animations/animation_storage_i.h b/applications/services/desktop/animations/animation_storage_i.h similarity index 100% rename from applications/desktop/animations/animation_storage_i.h rename to applications/services/desktop/animations/animation_storage_i.h diff --git a/applications/desktop/animations/views/bubble_animation_view.c b/applications/services/desktop/animations/views/bubble_animation_view.c similarity index 100% rename from applications/desktop/animations/views/bubble_animation_view.c rename to applications/services/desktop/animations/views/bubble_animation_view.c diff --git a/applications/desktop/animations/views/bubble_animation_view.h b/applications/services/desktop/animations/views/bubble_animation_view.h similarity index 100% rename from applications/desktop/animations/views/bubble_animation_view.h rename to applications/services/desktop/animations/views/bubble_animation_view.h diff --git a/applications/desktop/animations/views/one_shot_animation_view.c b/applications/services/desktop/animations/views/one_shot_animation_view.c similarity index 100% rename from applications/desktop/animations/views/one_shot_animation_view.c rename to applications/services/desktop/animations/views/one_shot_animation_view.c diff --git a/applications/desktop/animations/views/one_shot_animation_view.h b/applications/services/desktop/animations/views/one_shot_animation_view.h similarity index 100% rename from applications/desktop/animations/views/one_shot_animation_view.h rename to applications/services/desktop/animations/views/one_shot_animation_view.h diff --git a/applications/desktop/application.fam b/applications/services/desktop/application.fam similarity index 59% rename from applications/desktop/application.fam rename to applications/services/desktop/application.fam index 5f3dcdfd..da6e2b80 100644 --- a/applications/desktop/application.fam +++ b/applications/services/desktop/application.fam @@ -15,16 +15,3 @@ App( stack_size=2 * 1024, order=60, ) - -App( - appid="desktop_settings", - name="Desktop", - apptype=FlipperAppType.SETTINGS, - entry_point="desktop_settings_app", - requires=[ - "desktop", - "gui", - ], - stack_size=1 * 1024, - order=50, -) diff --git a/applications/desktop/desktop.c b/applications/services/desktop/desktop.c similarity index 86% rename from applications/desktop/desktop.c rename to applications/services/desktop/desktop.c index 578066a6..b45a9d62 100644 --- a/applications/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -32,13 +32,18 @@ static void desktop_loader_callback(const void* message, void* context) { view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalAfterAppFinished); } } - -static void desktop_lock_icon_callback(Canvas* canvas, void* context) { +static void desktop_lock_icon_draw_callback(Canvas* canvas, void* context) { UNUSED(context); furi_assert(canvas); canvas_draw_icon(canvas, 0, 0, &I_Lock_8x8); } +static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context) { + UNUSED(context); + furi_assert(canvas); + canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8); +} + static bool desktop_custom_event_callback(void* context, uint32_t event) { furi_assert(context); Desktop* desktop = (Desktop*)context; @@ -52,7 +57,7 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { animation_manager_load_and_continue_animation(desktop->animation_manager); // TODO: Implement a message mechanism for loading settings and (optionally) // locking and unlocking - LOAD_DESKTOP_SETTINGS(&desktop->settings); + DESKTOP_SETTINGS_LOAD(&desktop->settings); desktop_auto_lock_arm(desktop); return true; case DesktopGlobalAutoLock: @@ -127,7 +132,7 @@ void desktop_lock(Desktop* desktop) { } void desktop_unlock(Desktop* desktop) { - view_port_enabled_set(desktop->lock_viewport, false); + view_port_enabled_set(desktop->lock_icon_viewport, false); Gui* gui = furi_record_open(RECORD_GUI); gui_set_lockdown(gui, false); furi_record_close(RECORD_GUI); @@ -136,6 +141,13 @@ void desktop_unlock(Desktop* desktop) { desktop_auto_lock_arm(desktop); } +void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled) { + view_port_enabled_set(desktop->dummy_mode_icon_viewport, enabled); + desktop_main_set_dummy_mode_state(desktop->main_view, enabled); + desktop->settings.dummy_mode = enabled; + DESKTOP_SETTINGS_SAVE(&desktop->settings); +} + Desktop* desktop_alloc() { Desktop* desktop = malloc(sizeof(Desktop)); @@ -212,11 +224,20 @@ Desktop* desktop_alloc() { desktop_view_slideshow_get_view(desktop->slideshow_view)); // Lock icon - desktop->lock_viewport = view_port_alloc(); - view_port_set_width(desktop->lock_viewport, icon_get_width(&I_Lock_8x8)); - view_port_draw_callback_set(desktop->lock_viewport, desktop_lock_icon_callback, desktop); - view_port_enabled_set(desktop->lock_viewport, false); - gui_add_view_port(desktop->gui, desktop->lock_viewport, GuiLayerStatusBarLeft); + desktop->lock_icon_viewport = view_port_alloc(); + view_port_set_width(desktop->lock_icon_viewport, icon_get_width(&I_Lock_8x8)); + view_port_draw_callback_set( + desktop->lock_icon_viewport, desktop_lock_icon_draw_callback, desktop); + view_port_enabled_set(desktop->lock_icon_viewport, false); + gui_add_view_port(desktop->gui, desktop->lock_icon_viewport, GuiLayerStatusBarLeft); + + // Dummy mode icon + desktop->dummy_mode_icon_viewport = view_port_alloc(); + view_port_set_width(desktop->dummy_mode_icon_viewport, icon_get_width(&I_GameMode_11x8)); + view_port_draw_callback_set( + desktop->dummy_mode_icon_viewport, desktop_dummy_mode_icon_draw_callback, desktop); + view_port_enabled_set(desktop->dummy_mode_icon_viewport, false); + gui_add_view_port(desktop->gui, desktop->dummy_mode_icon_viewport, GuiLayerStatusBarLeft); // Special case: autostart application is already running desktop->loader = furi_record_open(RECORD_LOADER); @@ -301,12 +322,15 @@ int32_t desktop_srv(void* p) { UNUSED(p); Desktop* desktop = desktop_alloc(); - bool loaded = LOAD_DESKTOP_SETTINGS(&desktop->settings); + bool loaded = DESKTOP_SETTINGS_LOAD(&desktop->settings); if(!loaded) { memset(&desktop->settings, 0, sizeof(desktop->settings)); - SAVE_DESKTOP_SETTINGS(&desktop->settings); + DESKTOP_SETTINGS_SAVE(&desktop->settings); } + view_port_enabled_set(desktop->dummy_mode_icon_viewport, desktop->settings.dummy_mode); + desktop_main_set_dummy_mode_state(desktop->main_view, desktop->settings.dummy_mode); + scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain); desktop_pin_lock_init(&desktop->settings); diff --git a/applications/desktop/desktop.h b/applications/services/desktop/desktop.h similarity index 100% rename from applications/desktop/desktop.h rename to applications/services/desktop/desktop.h diff --git a/applications/desktop/desktop_i.h b/applications/services/desktop/desktop_i.h similarity index 91% rename from applications/desktop/desktop_i.h rename to applications/services/desktop/desktop_i.h index 0b5d607d..8034bbc3 100644 --- a/applications/desktop/desktop_i.h +++ b/applications/services/desktop/desktop_i.h @@ -9,7 +9,7 @@ #include "views/desktop_view_lock_menu.h" #include "views/desktop_view_debug.h" #include "views/desktop_view_slideshow.h" -#include "desktop/desktop_settings/desktop_settings.h" +#include #include #include @@ -57,7 +57,8 @@ struct Desktop { DesktopSettings settings; DesktopViewPinInput* pin_input_view; - ViewPort* lock_viewport; + ViewPort* lock_icon_viewport; + ViewPort* dummy_mode_icon_viewport; AnimationManager* animation_manager; @@ -75,3 +76,4 @@ Desktop* desktop_alloc(); void desktop_free(Desktop* desktop); void desktop_lock(Desktop* desktop); void desktop_unlock(Desktop* desktop); +void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled); diff --git a/applications/desktop/desktop_settings/desktop_settings.h b/applications/services/desktop/desktop_settings.h similarity index 89% rename from applications/desktop/desktop_settings/desktop_settings.h rename to applications/services/desktop/desktop_settings.h index 800847d5..3b10fbb1 100644 --- a/applications/desktop/desktop_settings/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -8,7 +8,7 @@ #include #include -#define DESKTOP_SETTINGS_VER (4) +#define DESKTOP_SETTINGS_VER (5) #define DESKTOP_SETTINGS_PATH INT_PATH(DESKTOP_SETTINGS_FILE_NAME) #define DESKTOP_SETTINGS_MAGIC (0x17) @@ -16,7 +16,7 @@ #define DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG "run_pin_setup" -#define SAVE_DESKTOP_SETTINGS(x) \ +#define DESKTOP_SETTINGS_SAVE(x) \ saved_struct_save( \ DESKTOP_SETTINGS_PATH, \ (x), \ @@ -24,7 +24,7 @@ DESKTOP_SETTINGS_MAGIC, \ DESKTOP_SETTINGS_VER) -#define LOAD_DESKTOP_SETTINGS(x) \ +#define DESKTOP_SETTINGS_LOAD(x) \ saved_struct_load( \ DESKTOP_SETTINGS_PATH, \ (x), \ @@ -46,4 +46,5 @@ typedef struct { PinCode pin_code; uint8_t is_locked; uint32_t auto_lock_delay_ms; + uint8_t dummy_mode; } DesktopSettings; diff --git a/applications/desktop/desktop_settings/desktop_settings_filename.h b/applications/services/desktop/desktop_settings_filename.h similarity index 100% rename from applications/desktop/desktop_settings/desktop_settings_filename.h rename to applications/services/desktop/desktop_settings_filename.h diff --git a/applications/desktop/helpers/pin_lock.c b/applications/services/desktop/helpers/pin_lock.c similarity index 96% rename from applications/desktop/helpers/pin_lock.c rename to applications/services/desktop/helpers/pin_lock.c index 0495b675..22fcabe7 100644 --- a/applications/desktop/helpers/pin_lock.c +++ b/applications/services/desktop/helpers/pin_lock.c @@ -8,6 +8,7 @@ #include "../helpers/pin_lock.h" #include "../desktop_i.h" +#include #include static const NotificationSequence sequence_pin_fail = { @@ -71,7 +72,7 @@ void desktop_pin_lock(DesktopSettings* settings) { cli_session_close(cli); furi_record_close(RECORD_CLI); settings->is_locked = 1; - SAVE_DESKTOP_SETTINGS(settings); + DESKTOP_SETTINGS_SAVE(settings); } void desktop_pin_unlock(DesktopSettings* settings) { @@ -82,7 +83,7 @@ void desktop_pin_unlock(DesktopSettings* settings) { cli_session_open(cli, &cli_vcp); furi_record_close(RECORD_CLI); settings->is_locked = 0; - SAVE_DESKTOP_SETTINGS(settings); + DESKTOP_SETTINGS_SAVE(settings); } void desktop_pin_lock_init(DesktopSettings* settings) { @@ -94,7 +95,7 @@ void desktop_pin_lock_init(DesktopSettings* settings) { } else { if(desktop_pin_lock_is_locked()) { settings->is_locked = 1; - SAVE_DESKTOP_SETTINGS(settings); + DESKTOP_SETTINGS_SAVE(settings); } } } else { diff --git a/applications/desktop/helpers/pin_lock.h b/applications/services/desktop/helpers/pin_lock.h similarity index 91% rename from applications/desktop/helpers/pin_lock.h rename to applications/services/desktop/helpers/pin_lock.h index 4454cda5..028ae6d2 100644 --- a/applications/desktop/helpers/pin_lock.h +++ b/applications/services/desktop/helpers/pin_lock.h @@ -2,7 +2,7 @@ #include #include #include "../desktop.h" -#include "../desktop_settings/desktop_settings.h" +#include void desktop_pin_lock_error_notify(); diff --git a/applications/desktop/helpers/slideshow.c b/applications/services/desktop/helpers/slideshow.c similarity index 100% rename from applications/desktop/helpers/slideshow.c rename to applications/services/desktop/helpers/slideshow.c diff --git a/applications/desktop/helpers/slideshow.h b/applications/services/desktop/helpers/slideshow.h similarity index 100% rename from applications/desktop/helpers/slideshow.h rename to applications/services/desktop/helpers/slideshow.h diff --git a/applications/desktop/helpers/slideshow_filename.h b/applications/services/desktop/helpers/slideshow_filename.h similarity index 100% rename from applications/desktop/helpers/slideshow_filename.h rename to applications/services/desktop/helpers/slideshow_filename.h diff --git a/applications/desktop/scenes/desktop_scene.c b/applications/services/desktop/scenes/desktop_scene.c similarity index 100% rename from applications/desktop/scenes/desktop_scene.c rename to applications/services/desktop/scenes/desktop_scene.c diff --git a/applications/desktop/scenes/desktop_scene.h b/applications/services/desktop/scenes/desktop_scene.h similarity index 100% rename from applications/desktop/scenes/desktop_scene.h rename to applications/services/desktop/scenes/desktop_scene.h diff --git a/applications/desktop/scenes/desktop_scene_config.h b/applications/services/desktop/scenes/desktop_scene_config.h similarity index 100% rename from applications/desktop/scenes/desktop_scene_config.h rename to applications/services/desktop/scenes/desktop_scene_config.h diff --git a/applications/desktop/scenes/desktop_scene_debug.c b/applications/services/desktop/scenes/desktop_scene_debug.c similarity index 100% rename from applications/desktop/scenes/desktop_scene_debug.c rename to applications/services/desktop/scenes/desktop_scene_debug.c diff --git a/applications/desktop/scenes/desktop_scene_fault.c b/applications/services/desktop/scenes/desktop_scene_fault.c similarity index 100% rename from applications/desktop/scenes/desktop_scene_fault.c rename to applications/services/desktop/scenes/desktop_scene_fault.c diff --git a/applications/desktop/scenes/desktop_scene_hw_mismatch.c b/applications/services/desktop/scenes/desktop_scene_hw_mismatch.c similarity index 100% rename from applications/desktop/scenes/desktop_scene_hw_mismatch.c rename to applications/services/desktop/scenes/desktop_scene_hw_mismatch.c diff --git a/applications/desktop/scenes/desktop_scene_i.h b/applications/services/desktop/scenes/desktop_scene_i.h similarity index 100% rename from applications/desktop/scenes/desktop_scene_i.h rename to applications/services/desktop/scenes/desktop_scene_i.h diff --git a/applications/desktop/scenes/desktop_scene_lock_menu.c b/applications/services/desktop/scenes/desktop_scene_lock_menu.c similarity index 75% rename from applications/desktop/scenes/desktop_scene_lock_menu.c rename to applications/services/desktop/scenes/desktop_scene_lock_menu.c index a86bb184..365fe170 100644 --- a/applications/desktop/scenes/desktop_scene_lock_menu.c +++ b/applications/services/desktop/scenes/desktop_scene_lock_menu.c @@ -6,7 +6,7 @@ #include #include "../desktop_i.h" -#include "../desktop_settings/desktop_settings.h" +#include #include "../views/desktop_view_lock_menu.h" #include "desktop_scene_i.h" #include "desktop_scene.h" @@ -22,10 +22,11 @@ void desktop_scene_lock_menu_callback(DesktopEvent event, void* context) { void desktop_scene_lock_menu_on_enter(void* context) { Desktop* desktop = (Desktop*)context; - LOAD_DESKTOP_SETTINGS(&desktop->settings); + DESKTOP_SETTINGS_LOAD(&desktop->settings); scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); desktop_lock_menu_set_callback(desktop->lock_menu, desktop_scene_lock_menu_callback, desktop); - desktop_lock_menu_pin_set(desktop->lock_menu, desktop->settings.pin_code.length > 0); + desktop_lock_menu_set_pin_state(desktop->lock_menu, desktop->settings.pin_code.length > 0); + desktop_lock_menu_set_dummy_mode_state(desktop->lock_menu, desktop->settings.dummy_mode); desktop_lock_menu_set_idx(desktop->lock_menu, 0); view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdLockMenu); @@ -39,9 +40,9 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { bool check_pin_changed = scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLockMenu); if(check_pin_changed) { - LOAD_DESKTOP_SETTINGS(&desktop->settings); + DESKTOP_SETTINGS_LOAD(&desktop->settings); if(desktop->settings.pin_code.length > 0) { - desktop_lock_menu_pin_set(desktop->lock_menu, 1); + desktop_lock_menu_set_pin_state(desktop->lock_menu, true); scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); } } @@ -67,15 +68,21 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { } consumed = true; break; - case DesktopLockMenuEventExit: - scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); + case DesktopLockMenuEventDummyModeOn: + desktop_set_dummy_mode_state(desktop, true); + scene_manager_search_and_switch_to_previous_scene( + desktop->scene_manager, DesktopSceneMain); + break; + case DesktopLockMenuEventDummyModeOff: + desktop_set_dummy_mode_state(desktop, false); scene_manager_search_and_switch_to_previous_scene( desktop->scene_manager, DesktopSceneMain); - consumed = true; break; default: break; } + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); } return consumed; } diff --git a/applications/desktop/scenes/desktop_scene_locked.c b/applications/services/desktop/scenes/desktop_scene_locked.c similarity index 97% rename from applications/desktop/scenes/desktop_scene_locked.c rename to applications/services/desktop/scenes/desktop_scene_locked.c index c377d40a..af19efc7 100644 --- a/applications/desktop/scenes/desktop_scene_locked.c +++ b/applications/services/desktop/scenes/desktop_scene_locked.c @@ -46,13 +46,13 @@ void desktop_scene_locked_on_enter(void* context) { uint32_t state = scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLocked); if(state == SCENE_LOCKED_FIRST_ENTER) { bool pin_locked = desktop_pin_lock_is_locked(); - view_port_enabled_set(desktop->lock_viewport, true); + view_port_enabled_set(desktop->lock_icon_viewport, true); Gui* gui = furi_record_open(RECORD_GUI); gui_set_lockdown(gui, true); furi_record_close(RECORD_GUI); if(pin_locked) { - LOAD_DESKTOP_SETTINGS(&desktop->settings); + DESKTOP_SETTINGS_LOAD(&desktop->settings); desktop_view_locked_lock(desktop->locked_view, true); uint32_t pin_timeout = desktop_pin_lock_get_fail_timeout(); if(pin_timeout > 0) { diff --git a/applications/desktop/scenes/desktop_scene_main.c b/applications/services/desktop/scenes/desktop_scene_main.c similarity index 89% rename from applications/desktop/scenes/desktop_scene_main.c rename to applications/services/desktop/scenes/desktop_scene_main.c index bc4101ff..dc9ac04d 100644 --- a/applications/desktop/scenes/desktop_scene_main.c +++ b/applications/services/desktop/scenes/desktop_scene_main.c @@ -113,7 +113,7 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { } case DesktopMainEventOpenFavoritePrimary: - LOAD_DESKTOP_SETTINGS(&desktop->settings); + DESKTOP_SETTINGS_LOAD(&desktop->settings); if(desktop->settings.favorite_primary < FLIPPER_APPS_COUNT) { LoaderStatus status = loader_start( desktop->loader, FLIPPER_APPS[desktop->settings.favorite_primary].name, NULL); @@ -126,7 +126,7 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { consumed = true; break; case DesktopMainEventOpenFavoriteSecondary: - LOAD_DESKTOP_SETTINGS(&desktop->settings); + DESKTOP_SETTINGS_LOAD(&desktop->settings); if(desktop->settings.favorite_secondary < FLIPPER_APPS_COUNT) { LoaderStatus status = loader_start( desktop->loader, @@ -157,6 +157,21 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { } consumed = true; break; + case DesktopMainEventOpenPassport: { + LoaderStatus status = loader_start(desktop->loader, "Passport", NULL); + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } + break; + } + case DesktopMainEventOpenGameMenu: { + LoaderStatus status = loader_start( + desktop->loader, "Applications", EXT_PATH("/apps/Games/snake_game.fap")); + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } + break; + } case DesktopLockedEventUpdate: desktop_view_locked_update(desktop->locked_view); consumed = true; diff --git a/applications/desktop/scenes/desktop_scene_pin_input.c b/applications/services/desktop/scenes/desktop_scene_pin_input.c similarity index 100% rename from applications/desktop/scenes/desktop_scene_pin_input.c rename to applications/services/desktop/scenes/desktop_scene_pin_input.c diff --git a/applications/desktop/scenes/desktop_scene_pin_timeout.c b/applications/services/desktop/scenes/desktop_scene_pin_timeout.c similarity index 100% rename from applications/desktop/scenes/desktop_scene_pin_timeout.c rename to applications/services/desktop/scenes/desktop_scene_pin_timeout.c diff --git a/applications/desktop/scenes/desktop_scene_slideshow.c b/applications/services/desktop/scenes/desktop_scene_slideshow.c similarity index 88% rename from applications/desktop/scenes/desktop_scene_slideshow.c rename to applications/services/desktop/scenes/desktop_scene_slideshow.c index cab7bf62..012aff75 100644 --- a/applications/desktop/scenes/desktop_scene_slideshow.c +++ b/applications/services/desktop/scenes/desktop_scene_slideshow.c @@ -22,15 +22,11 @@ void desktop_scene_slideshow_on_enter(void* context) { bool desktop_scene_slideshow_on_event(void* context, SceneManagerEvent event) { Desktop* desktop = (Desktop*)context; bool consumed = false; - Storage* storage = NULL; Power* power = NULL; if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { case DesktopSlideshowCompleted: - storage = furi_record_open(RECORD_STORAGE); - storage_common_remove(storage, SLIDESHOW_FS_PATH); - furi_record_close(RECORD_STORAGE); scene_manager_previous_scene(desktop->scene_manager); consumed = true; break; @@ -50,4 +46,8 @@ bool desktop_scene_slideshow_on_event(void* context, SceneManagerEvent event) { void desktop_scene_slideshow_on_exit(void* context) { UNUSED(context); + + Storage* storage = furi_record_open(RECORD_STORAGE); + storage_common_remove(storage, SLIDESHOW_FS_PATH); + furi_record_close(RECORD_STORAGE); } diff --git a/applications/desktop/views/desktop_events.h b/applications/services/desktop/views/desktop_events.h similarity index 88% rename from applications/desktop/views/desktop_events.h rename to applications/services/desktop/views/desktop_events.h index 5d130be9..a7e610ff 100644 --- a/applications/desktop/views/desktop_events.h +++ b/applications/services/desktop/views/desktop_events.h @@ -7,9 +7,11 @@ typedef enum { DesktopMainEventOpenFavoriteSecondary, DesktopMainEventOpenMenu, DesktopMainEventOpenDebug, - DesktopMainEventOpenPassport, /**< Broken, don't use it */ + DesktopMainEventOpenPassport, DesktopMainEventOpenPowerOff, + DesktopMainEventOpenGameMenu, + DesktopLockedEventUnlocked, DesktopLockedEventUpdate, DesktopLockedEventShowPinInput, @@ -28,7 +30,8 @@ typedef enum { DesktopLockMenuEventLock, DesktopLockMenuEventPinLock, - DesktopLockMenuEventExit, + DesktopLockMenuEventDummyModeOn, + DesktopLockMenuEventDummyModeOff, DesktopAnimationEventCheckAnimation, DesktopAnimationEventNewIdleAnimation, diff --git a/applications/desktop/views/desktop_view_debug.c b/applications/services/desktop/views/desktop_view_debug.c similarity index 100% rename from applications/desktop/views/desktop_view_debug.c rename to applications/services/desktop/views/desktop_view_debug.c diff --git a/applications/desktop/views/desktop_view_debug.h b/applications/services/desktop/views/desktop_view_debug.h similarity index 100% rename from applications/desktop/views/desktop_view_debug.h rename to applications/services/desktop/views/desktop_view_debug.h diff --git a/applications/services/desktop/views/desktop_view_lock_menu.c b/applications/services/desktop/views/desktop_view_lock_menu.c new file mode 100644 index 00000000..294191bf --- /dev/null +++ b/applications/services/desktop/views/desktop_view_lock_menu.c @@ -0,0 +1,160 @@ +#include +#include + +#include "../desktop_i.h" +#include "desktop_view_lock_menu.h" + +typedef enum { + DesktopLockMenuIndexLock, + DesktopLockMenuIndexPinLock, + DesktopLockMenuIndexDummy, + + DesktopLockMenuIndexTotalCount +} DesktopLockMenuIndex; + +void desktop_lock_menu_set_callback( + DesktopLockMenuView* lock_menu, + DesktopLockMenuViewCallback callback, + void* context) { + furi_assert(lock_menu); + furi_assert(callback); + lock_menu->callback = callback; + lock_menu->context = context; +} + +void desktop_lock_menu_set_pin_state(DesktopLockMenuView* lock_menu, bool pin_is_set) { + with_view_model( + lock_menu->view, (DesktopLockMenuViewModel * model) { + model->pin_is_set = pin_is_set; + return true; + }); +} + +void desktop_lock_menu_set_dummy_mode_state(DesktopLockMenuView* lock_menu, bool dummy_mode) { + with_view_model( + lock_menu->view, (DesktopLockMenuViewModel * model) { + model->dummy_mode = dummy_mode; + return true; + }); +} + +void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx) { + furi_assert(idx < DesktopLockMenuIndexTotalCount); + with_view_model( + lock_menu->view, (DesktopLockMenuViewModel * model) { + model->idx = idx; + return true; + }); +} + +void desktop_lock_menu_draw_callback(Canvas* canvas, void* model) { + DesktopLockMenuViewModel* m = model; + + canvas_set_color(canvas, ColorBlack); + canvas_draw_icon(canvas, -57, 0 + STATUS_BAR_Y_SHIFT, &I_DoorLeft_70x55); + canvas_draw_icon(canvas, 116, 0 + STATUS_BAR_Y_SHIFT, &I_DoorRight_70x55); + canvas_set_font(canvas, FontSecondary); + + for(uint8_t i = 0; i < DesktopLockMenuIndexTotalCount; ++i) { + const char* str = NULL; + + if(i == DesktopLockMenuIndexLock) { + str = "Lock"; + } else if(i == DesktopLockMenuIndexPinLock) { + if(m->pin_is_set) { + str = "Lock with PIN"; + } else { + str = "Set PIN"; + } + } else if(i == DesktopLockMenuIndexDummy) { + if(m->dummy_mode) { + str = "Brainiac Mode"; + } else { + str = "Dummy Mode"; + } + } + + if(str) + canvas_draw_str_aligned( + canvas, 64, 9 + (i * 17) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str); + + if(m->idx == i) elements_frame(canvas, 15, 1 + (i * 17) + STATUS_BAR_Y_SHIFT, 98, 15); + } +} + +View* desktop_lock_menu_get_view(DesktopLockMenuView* lock_menu) { + furi_assert(lock_menu); + return lock_menu->view; +} + +bool desktop_lock_menu_input_callback(InputEvent* event, void* context) { + furi_assert(event); + furi_assert(context); + + DesktopLockMenuView* lock_menu = context; + uint8_t idx = 0; + bool consumed = false; + bool dummy_mode = false; + + with_view_model( + lock_menu->view, (DesktopLockMenuViewModel * model) { + bool ret = false; + if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { + if(event->key == InputKeyUp) { + if(model->idx == 0) { + model->idx = DesktopLockMenuIndexTotalCount - 1; + } else { + model->idx = CLAMP(model->idx - 1, DesktopLockMenuIndexTotalCount - 1, 0); + } + ret = true; + consumed = true; + } else if(event->key == InputKeyDown) { + if(model->idx == DesktopLockMenuIndexTotalCount - 1) { + model->idx = 0; + } else { + model->idx = CLAMP(model->idx + 1, DesktopLockMenuIndexTotalCount - 1, 0); + } + ret = true; + consumed = true; + } + } + idx = model->idx; + dummy_mode = model->dummy_mode; + return ret; + }); + + if(event->key == InputKeyOk) { + if((idx == DesktopLockMenuIndexLock) && (event->type == InputTypeShort)) { + lock_menu->callback(DesktopLockMenuEventLock, lock_menu->context); + } else if((idx == DesktopLockMenuIndexPinLock) && (event->type == InputTypeShort)) { + lock_menu->callback(DesktopLockMenuEventPinLock, lock_menu->context); + } else if(idx == DesktopLockMenuIndexDummy) { + if((dummy_mode == false) && (event->type == InputTypeShort)) { + lock_menu->callback(DesktopLockMenuEventDummyModeOn, lock_menu->context); + } else if((dummy_mode == true) && (event->type == InputTypeShort)) { + lock_menu->callback(DesktopLockMenuEventDummyModeOff, lock_menu->context); + } + } + consumed = true; + } + + return consumed; +} + +DesktopLockMenuView* desktop_lock_menu_alloc() { + DesktopLockMenuView* lock_menu = malloc(sizeof(DesktopLockMenuView)); + lock_menu->view = view_alloc(); + view_allocate_model(lock_menu->view, ViewModelTypeLocking, sizeof(DesktopLockMenuViewModel)); + view_set_context(lock_menu->view, lock_menu); + view_set_draw_callback(lock_menu->view, (ViewDrawCallback)desktop_lock_menu_draw_callback); + view_set_input_callback(lock_menu->view, desktop_lock_menu_input_callback); + + return lock_menu; +} + +void desktop_lock_menu_free(DesktopLockMenuView* lock_menu_view) { + furi_assert(lock_menu_view); + + view_free(lock_menu_view->view); + free(lock_menu_view); +} diff --git a/applications/desktop/views/desktop_view_lock_menu.h b/applications/services/desktop/views/desktop_view_lock_menu.h similarity index 77% rename from applications/desktop/views/desktop_view_lock_menu.h rename to applications/services/desktop/views/desktop_view_lock_menu.h index e9928a38..812aa9f9 100644 --- a/applications/desktop/views/desktop_view_lock_menu.h +++ b/applications/services/desktop/views/desktop_view_lock_menu.h @@ -17,8 +17,8 @@ struct DesktopLockMenuView { typedef struct { uint8_t idx; - uint8_t hint_timeout; - bool pin_set; + bool pin_is_set; + bool dummy_mode; } DesktopLockMenuViewModel; void desktop_lock_menu_set_callback( @@ -27,7 +27,8 @@ void desktop_lock_menu_set_callback( void* context); View* desktop_lock_menu_get_view(DesktopLockMenuView* lock_menu); -void desktop_lock_menu_pin_set(DesktopLockMenuView* lock_menu, bool pin_is_set); +void desktop_lock_menu_set_pin_state(DesktopLockMenuView* lock_menu, bool pin_is_set); +void desktop_lock_menu_set_dummy_mode_state(DesktopLockMenuView* lock_menu, bool dummy_mode); void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx); DesktopLockMenuView* desktop_lock_menu_alloc(); void desktop_lock_menu_free(DesktopLockMenuView* lock_menu); diff --git a/applications/desktop/views/desktop_view_locked.c b/applications/services/desktop/views/desktop_view_locked.c similarity index 99% rename from applications/desktop/views/desktop_view_locked.c rename to applications/services/desktop/views/desktop_view_locked.c index 58ed4fac..915b2610 100644 --- a/applications/desktop/views/desktop_view_locked.c +++ b/applications/services/desktop/views/desktop_view_locked.c @@ -6,7 +6,7 @@ #include #include -#include "../desktop_settings/desktop_settings.h" +#include #include "../desktop_i.h" #include "desktop_view_locked.h" diff --git a/applications/desktop/views/desktop_view_locked.h b/applications/services/desktop/views/desktop_view_locked.h similarity index 94% rename from applications/desktop/views/desktop_view_locked.h rename to applications/services/desktop/views/desktop_view_locked.h index b0a0aa30..ea065e39 100644 --- a/applications/desktop/views/desktop_view_locked.h +++ b/applications/services/desktop/views/desktop_view_locked.h @@ -1,6 +1,6 @@ #pragma once -#include "../desktop_settings/desktop_settings.h" +#include #include "../views/desktop_events.h" #include diff --git a/applications/desktop/views/desktop_view_main.c b/applications/services/desktop/views/desktop_view_main.c similarity index 52% rename from applications/desktop/views/desktop_view_main.c rename to applications/services/desktop/views/desktop_view_main.c index 2b1d61f4..0edc0b70 100644 --- a/applications/desktop/views/desktop_view_main.c +++ b/applications/services/desktop/views/desktop_view_main.c @@ -14,6 +14,7 @@ struct DesktopMainView { DesktopMainViewCallback callback; void* context; TimerHandle_t poweroff_timer; + bool dummy_mode; }; #define DESKTOP_MAIN_VIEW_POWEROFF_TIMEOUT 5000 @@ -38,29 +39,48 @@ View* desktop_main_get_view(DesktopMainView* main_view) { return main_view->view; } -bool desktop_main_input(InputEvent* event, void* context) { +void desktop_main_set_dummy_mode_state(DesktopMainView* main_view, bool dummy_mode) { + furi_assert(main_view); + main_view->dummy_mode = dummy_mode; +} + +bool desktop_main_input_callback(InputEvent* event, void* context) { furi_assert(event); furi_assert(context); DesktopMainView* main_view = context; - if(event->type == InputTypeShort) { - if(event->key == InputKeyOk) { - main_view->callback(DesktopMainEventOpenMenu, main_view->context); - } else if(event->key == InputKeyUp) { - main_view->callback(DesktopMainEventOpenLockMenu, main_view->context); - } else if(event->key == InputKeyDown) { - main_view->callback(DesktopMainEventOpenArchive, main_view->context); - } else if(event->key == InputKeyLeft) { - main_view->callback(DesktopMainEventOpenFavoritePrimary, main_view->context); - } else if(event->key == InputKeyRight) { - main_view->callback(DesktopMainEventOpenPassport, main_view->context); + if(main_view->dummy_mode == false) { + if(event->type == InputTypeShort) { + if(event->key == InputKeyOk) { + main_view->callback(DesktopMainEventOpenMenu, main_view->context); + } else if(event->key == InputKeyUp) { + main_view->callback(DesktopMainEventOpenLockMenu, main_view->context); + } else if(event->key == InputKeyDown) { + main_view->callback(DesktopMainEventOpenArchive, main_view->context); + } else if(event->key == InputKeyLeft) { + main_view->callback(DesktopMainEventOpenFavoritePrimary, main_view->context); + } + // Right key is handled by animation manager + } else if(event->type == InputTypeLong) { + if(event->key == InputKeyDown) { + main_view->callback(DesktopMainEventOpenDebug, main_view->context); + } else if(event->key == InputKeyLeft) { + main_view->callback(DesktopMainEventOpenFavoriteSecondary, main_view->context); + } } - } else if(event->type == InputTypeLong) { - if(event->key == InputKeyDown) { - main_view->callback(DesktopMainEventOpenDebug, main_view->context); - } else if(event->key == InputKeyLeft) { - main_view->callback(DesktopMainEventOpenFavoriteSecondary, main_view->context); + } else { + if(event->type == InputTypeShort) { + if(event->key == InputKeyOk) { + main_view->callback(DesktopMainEventOpenGameMenu, main_view->context); + } else if(event->key == InputKeyUp) { + main_view->callback(DesktopMainEventOpenLockMenu, main_view->context); + } else if(event->key == InputKeyDown) { + main_view->callback(DesktopMainEventOpenPassport, main_view->context); + } else if(event->key == InputKeyLeft) { + main_view->callback(DesktopMainEventOpenPassport, main_view->context); + } + // Right key is handled by animation manager } } @@ -84,7 +104,7 @@ DesktopMainView* desktop_main_alloc() { main_view->view = view_alloc(); view_allocate_model(main_view->view, ViewModelTypeLockFree, 1); view_set_context(main_view->view, main_view); - view_set_input_callback(main_view->view, desktop_main_input); + view_set_input_callback(main_view->view, desktop_main_input_callback); main_view->poweroff_timer = xTimerCreate( NULL, diff --git a/applications/desktop/views/desktop_view_main.h b/applications/services/desktop/views/desktop_view_main.h similarity index 84% rename from applications/desktop/views/desktop_view_main.h rename to applications/services/desktop/views/desktop_view_main.h index 329d9548..b5492b1b 100644 --- a/applications/desktop/views/desktop_view_main.h +++ b/applications/services/desktop/views/desktop_view_main.h @@ -13,5 +13,6 @@ void desktop_main_set_callback( void* context); View* desktop_main_get_view(DesktopMainView* main_view); +void desktop_main_set_dummy_mode_state(DesktopMainView* main_view, bool dummy_mode); DesktopMainView* desktop_main_alloc(); void desktop_main_free(DesktopMainView* main_view); diff --git a/applications/desktop/views/desktop_view_pin_input.c b/applications/services/desktop/views/desktop_view_pin_input.c similarity index 99% rename from applications/desktop/views/desktop_view_pin_input.c rename to applications/services/desktop/views/desktop_view_pin_input.c index d6ce1a02..bf05f06b 100644 --- a/applications/desktop/views/desktop_view_pin_input.c +++ b/applications/services/desktop/views/desktop_view_pin_input.c @@ -6,7 +6,7 @@ #include #include "desktop_view_pin_input.h" -#include "../desktop_settings/desktop_settings.h" +#include #define NO_ACTIVITY_TIMEOUT 15000 @@ -117,7 +117,7 @@ static void desktop_view_pin_input_draw_cells(Canvas* canvas, DesktopViewPinInpu canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_down_7x9); break; case InputKeyUp: - canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_up7x9); + canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_up_7x9); break; case InputKeyLeft: canvas_draw_icon(canvas, x + 2, y + 3, &I_Pin_arrow_left_9x7); diff --git a/applications/desktop/views/desktop_view_pin_input.h b/applications/services/desktop/views/desktop_view_pin_input.h similarity index 96% rename from applications/desktop/views/desktop_view_pin_input.h rename to applications/services/desktop/views/desktop_view_pin_input.h index 3e39fd20..40eee4cc 100644 --- a/applications/desktop/views/desktop_view_pin_input.h +++ b/applications/services/desktop/views/desktop_view_pin_input.h @@ -1,7 +1,7 @@ #pragma once #include -#include "desktop/desktop_settings/desktop_settings.h" +#include typedef void (*DesktopViewPinInputCallback)(void*); typedef void (*DesktopViewPinInputDoneCallback)(const PinCode* pin_code, void*); diff --git a/applications/desktop/views/desktop_view_pin_setup_done.c b/applications/services/desktop/views/desktop_view_pin_setup_done.c similarity index 100% rename from applications/desktop/views/desktop_view_pin_setup_done.c rename to applications/services/desktop/views/desktop_view_pin_setup_done.c diff --git a/applications/desktop/views/desktop_view_pin_setup_done.h b/applications/services/desktop/views/desktop_view_pin_setup_done.h similarity index 100% rename from applications/desktop/views/desktop_view_pin_setup_done.h rename to applications/services/desktop/views/desktop_view_pin_setup_done.h diff --git a/applications/desktop/views/desktop_view_pin_timeout.c b/applications/services/desktop/views/desktop_view_pin_timeout.c similarity index 100% rename from applications/desktop/views/desktop_view_pin_timeout.c rename to applications/services/desktop/views/desktop_view_pin_timeout.c diff --git a/applications/desktop/views/desktop_view_pin_timeout.h b/applications/services/desktop/views/desktop_view_pin_timeout.h similarity index 100% rename from applications/desktop/views/desktop_view_pin_timeout.h rename to applications/services/desktop/views/desktop_view_pin_timeout.h diff --git a/applications/desktop/views/desktop_view_slideshow.c b/applications/services/desktop/views/desktop_view_slideshow.c similarity index 100% rename from applications/desktop/views/desktop_view_slideshow.c rename to applications/services/desktop/views/desktop_view_slideshow.c diff --git a/applications/desktop/views/desktop_view_slideshow.h b/applications/services/desktop/views/desktop_view_slideshow.h similarity index 100% rename from applications/desktop/views/desktop_view_slideshow.h rename to applications/services/desktop/views/desktop_view_slideshow.h diff --git a/applications/dialogs/application.fam b/applications/services/dialogs/application.fam similarity index 87% rename from applications/dialogs/application.fam rename to applications/services/dialogs/application.fam index 0a18c79a..eb2b40e2 100644 --- a/applications/dialogs/application.fam +++ b/applications/services/dialogs/application.fam @@ -7,4 +7,5 @@ App( requires=["gui"], stack_size=1 * 1024, order=40, + sdk_headers=["dialogs.h"], ) diff --git a/applications/dialogs/dialogs.c b/applications/services/dialogs/dialogs.c similarity index 78% rename from applications/dialogs/dialogs.c rename to applications/services/dialogs/dialogs.c index 381da163..e2db4a0f 100644 --- a/applications/dialogs/dialogs.c +++ b/applications/services/dialogs/dialogs.c @@ -4,6 +4,18 @@ #include "dialogs_module_file_browser.h" #include "dialogs_module_message.h" +void dialog_file_browser_set_basic_options( + DialogsFileBrowserOptions* options, + const char* extension, + const Icon* icon) { + options->extension = extension; + options->skip_assets = true; + options->icon = icon; + options->hide_ext = true; + options->item_loader_callback = NULL; + options->item_loader_context = NULL; +} + static DialogsApp* dialogs_app_alloc() { DialogsApp* app = malloc(sizeof(DialogsApp)); app->message_queue = furi_message_queue_alloc(8, sizeof(DialogsAppMessage)); diff --git a/applications/dialogs/dialogs.h b/applications/services/dialogs/dialogs.h similarity index 80% rename from applications/dialogs/dialogs.h rename to applications/services/dialogs/dialogs.h index 946ab6cf..2522c8b5 100644 --- a/applications/dialogs/dialogs.h +++ b/applications/services/dialogs/dialogs.h @@ -2,6 +2,7 @@ #include #include #include "m-string.h" +#include #ifdef __cplusplus extern "C" { @@ -16,24 +17,48 @@ typedef struct DialogsApp DialogsApp; /****************** FILE BROWSER ******************/ /** - * Shows and processes the file browser dialog - * @param context api pointer - * @param result_path selected file path string pointer - * @param path preselected file path string pointer + * File browser dialog extra options * @param extension file extension to be offered for selection * @param skip_assets true - do not show assets folders * @param icon file icon pointer, NULL for default icon * @param hide_ext true - hide extensions for files + * @param item_loader_callback callback function for providing custom icon & entry name + * @param hide_ext callback context + */ +typedef struct { + const char* extension; + bool skip_assets; + const Icon* icon; + bool hide_ext; + FileBrowserLoadItemCallback item_loader_callback; + void* item_loader_context; +} DialogsFileBrowserOptions; + +/** + * Initialize file browser dialog options + * and set default values + * @param options pointer to options structure + * @param extension file extension to filter + * @param icon file icon pointer, NULL for default icon + */ +void dialog_file_browser_set_basic_options( + DialogsFileBrowserOptions* options, + const char* extension, + const Icon* icon); + +/** + * Shows and processes the file browser dialog + * @param context api pointer + * @param result_path selected file path string pointer + * @param path preselected file path string pointer + * @param options file browser dialog extra options, may be null * @return bool whether a file was selected */ bool dialog_file_browser_show( DialogsApp* context, string_ptr result_path, string_ptr path, - const char* extension, - bool skip_assets, - const Icon* icon, - bool hide_ext); + const DialogsFileBrowserOptions* options); /****************** MESSAGE ******************/ diff --git a/applications/dialogs/dialogs_api.c b/applications/services/dialogs/dialogs_api.c similarity index 82% rename from applications/dialogs/dialogs_api.c rename to applications/services/dialogs/dialogs_api.c index 72aa2a1b..fd3b2e96 100644 --- a/applications/dialogs/dialogs_api.c +++ b/applications/services/dialogs/dialogs_api.c @@ -9,22 +9,20 @@ bool dialog_file_browser_show( DialogsApp* context, string_ptr result_path, string_ptr path, - const char* extension, - bool skip_assets, - const Icon* icon, - bool hide_ext) { + const DialogsFileBrowserOptions* options) { FuriApiLock lock = API_LOCK_INIT_LOCKED(); furi_check(lock != NULL); DialogsAppData data = { .file_browser = { - .extension = extension, + .extension = options ? options->extension : "", .result_path = result_path, - .file_icon = icon, - .hide_ext = hide_ext, - .skip_assets = skip_assets, + .file_icon = options ? options->icon : NULL, + .hide_ext = options ? options->hide_ext : true, + .skip_assets = options ? options->skip_assets : true, .preselected_filename = path, - + .item_callback = options ? options->item_loader_callback : NULL, + .item_callback_context = options ? options->item_loader_context : NULL, }}; DialogsAppReturn return_data; diff --git a/applications/dialogs/dialogs_api_lock.h b/applications/services/dialogs/dialogs_api_lock.h similarity index 100% rename from applications/dialogs/dialogs_api_lock.h rename to applications/services/dialogs/dialogs_api_lock.h diff --git a/applications/dialogs/dialogs_i.h b/applications/services/dialogs/dialogs_i.h similarity index 85% rename from applications/dialogs/dialogs_i.h rename to applications/services/dialogs/dialogs_i.h index 36bee024..76495d31 100644 --- a/applications/dialogs/dialogs_i.h +++ b/applications/services/dialogs/dialogs_i.h @@ -2,6 +2,7 @@ #include "dialogs.h" #include "dialogs_message.h" #include "view_holder.h" +#include #ifdef __cplusplus extern "C" { diff --git a/applications/dialogs/dialogs_message.h b/applications/services/dialogs/dialogs_message.h similarity index 92% rename from applications/dialogs/dialogs_message.h rename to applications/services/dialogs/dialogs_message.h index ccfbdece..2dc66f13 100644 --- a/applications/dialogs/dialogs_message.h +++ b/applications/services/dialogs/dialogs_message.h @@ -15,6 +15,8 @@ typedef struct { const Icon* file_icon; string_ptr result_path; string_ptr preselected_filename; + FileBrowserLoadItemCallback item_callback; + void* item_callback_context; } DialogsAppMessageDataFileBrowser; typedef struct { diff --git a/applications/dialogs/dialogs_module_file_browser.c b/applications/services/dialogs/dialogs_module_file_browser.c similarity index 95% rename from applications/dialogs/dialogs_module_file_browser.c rename to applications/services/dialogs/dialogs_module_file_browser.c index f5355571..166fd111 100644 --- a/applications/dialogs/dialogs_module_file_browser.c +++ b/applications/services/dialogs/dialogs_module_file_browser.c @@ -39,6 +39,7 @@ bool dialogs_app_process_module_file_browser(const DialogsAppMessageDataFileBrow file_browser, dialogs_app_file_browser_callback, file_browser_context); file_browser_configure( file_browser, data->extension, data->skip_assets, data->file_icon, data->hide_ext); + file_browser_set_item_callback(file_browser, data->item_callback, data->item_callback_context); file_browser_start(file_browser, data->preselected_filename); view_holder_set_view(view_holder, file_browser_get_view(file_browser)); diff --git a/applications/dialogs/dialogs_module_file_browser.h b/applications/services/dialogs/dialogs_module_file_browser.h similarity index 100% rename from applications/dialogs/dialogs_module_file_browser.h rename to applications/services/dialogs/dialogs_module_file_browser.h diff --git a/applications/dialogs/dialogs_module_message.c b/applications/services/dialogs/dialogs_module_message.c similarity index 100% rename from applications/dialogs/dialogs_module_message.c rename to applications/services/dialogs/dialogs_module_message.c diff --git a/applications/dialogs/dialogs_module_message.h b/applications/services/dialogs/dialogs_module_message.h similarity index 100% rename from applications/dialogs/dialogs_module_message.h rename to applications/services/dialogs/dialogs_module_message.h diff --git a/applications/dialogs/view_holder.c b/applications/services/dialogs/view_holder.c similarity index 100% rename from applications/dialogs/view_holder.c rename to applications/services/dialogs/view_holder.c diff --git a/applications/dialogs/view_holder.h b/applications/services/dialogs/view_holder.h similarity index 100% rename from applications/dialogs/view_holder.h rename to applications/services/dialogs/view_holder.h diff --git a/applications/services/dolphin/application.fam b/applications/services/dolphin/application.fam new file mode 100644 index 00000000..78a097e6 --- /dev/null +++ b/applications/services/dolphin/application.fam @@ -0,0 +1,10 @@ +App( + appid="dolphin", + name="DolphinSrv", + apptype=FlipperAppType.SERVICE, + entry_point="dolphin_srv", + cdefines=["SRV_DOLPHIN"], + stack_size=1 * 1024, + order=50, + sdk_headers=["dolphin.h"], +) diff --git a/applications/dolphin/dolphin.c b/applications/services/dolphin/dolphin.c similarity index 100% rename from applications/dolphin/dolphin.c rename to applications/services/dolphin/dolphin.c diff --git a/applications/dolphin/dolphin.h b/applications/services/dolphin/dolphin.h similarity index 100% rename from applications/dolphin/dolphin.h rename to applications/services/dolphin/dolphin.h diff --git a/applications/dolphin/dolphin_i.h b/applications/services/dolphin/dolphin_i.h similarity index 100% rename from applications/dolphin/dolphin_i.h rename to applications/services/dolphin/dolphin_i.h diff --git a/applications/dolphin/helpers/dolphin_deed.c b/applications/services/dolphin/helpers/dolphin_deed.c similarity index 100% rename from applications/dolphin/helpers/dolphin_deed.c rename to applications/services/dolphin/helpers/dolphin_deed.c diff --git a/applications/dolphin/helpers/dolphin_deed.h b/applications/services/dolphin/helpers/dolphin_deed.h similarity index 100% rename from applications/dolphin/helpers/dolphin_deed.h rename to applications/services/dolphin/helpers/dolphin_deed.h diff --git a/applications/dolphin/helpers/dolphin_state.c b/applications/services/dolphin/helpers/dolphin_state.c similarity index 100% rename from applications/dolphin/helpers/dolphin_state.c rename to applications/services/dolphin/helpers/dolphin_state.c diff --git a/applications/dolphin/helpers/dolphin_state.h b/applications/services/dolphin/helpers/dolphin_state.h similarity index 100% rename from applications/dolphin/helpers/dolphin_state.h rename to applications/services/dolphin/helpers/dolphin_state.h diff --git a/applications/dolphin/helpers/dolphin_state_filename.h b/applications/services/dolphin/helpers/dolphin_state_filename.h similarity index 100% rename from applications/dolphin/helpers/dolphin_state_filename.h rename to applications/services/dolphin/helpers/dolphin_state_filename.h diff --git a/applications/services/gui/application.fam b/applications/services/gui/application.fam new file mode 100644 index 00000000..7fad7b4e --- /dev/null +++ b/applications/services/gui/application.fam @@ -0,0 +1,36 @@ +App( + appid="gui", + name="GuiSrv", + apptype=FlipperAppType.SERVICE, + entry_point="gui_srv", + cdefines=["SRV_GUI"], + requires=[ + "input", + "notification", + ], + stack_size=2 * 1024, + order=70, + sdk_headers=[ + "gui.h", + "elements.h", + "view_dispatcher.h", + "view_stack.h", + "modules/button_menu.h", + "modules/byte_input.h", + "modules/popup.h", + "modules/text_input.h", + "modules/widget.h", + "modules/validators.h", + "modules/file_browser.h", + "modules/button_panel.h", + "modules/variable_item_list.h", + "modules/file_browser_worker.h", + "modules/menu.h", + "modules/dialog_ex.h", + "modules/loading.h", + "modules/text_box.h", + "modules/submenu.h", + "modules/widget_elements/widget_element.h", + "modules/empty_screen.h", + ], +) diff --git a/applications/gui/canvas.c b/applications/services/gui/canvas.c similarity index 100% rename from applications/gui/canvas.c rename to applications/services/gui/canvas.c diff --git a/applications/gui/canvas.h b/applications/services/gui/canvas.h similarity index 100% rename from applications/gui/canvas.h rename to applications/services/gui/canvas.h diff --git a/applications/gui/canvas_i.h b/applications/services/gui/canvas_i.h similarity index 100% rename from applications/gui/canvas_i.h rename to applications/services/gui/canvas_i.h diff --git a/applications/gui/elements.c b/applications/services/gui/elements.c similarity index 100% rename from applications/gui/elements.c rename to applications/services/gui/elements.c diff --git a/applications/gui/elements.h b/applications/services/gui/elements.h similarity index 100% rename from applications/gui/elements.h rename to applications/services/gui/elements.h diff --git a/applications/gui/gui.c b/applications/services/gui/gui.c similarity index 100% rename from applications/gui/gui.c rename to applications/services/gui/gui.c diff --git a/applications/gui/gui.h b/applications/services/gui/gui.h similarity index 100% rename from applications/gui/gui.h rename to applications/services/gui/gui.h diff --git a/applications/gui/gui_i.h b/applications/services/gui/gui_i.h similarity index 100% rename from applications/gui/gui_i.h rename to applications/services/gui/gui_i.h diff --git a/applications/gui/icon.c b/applications/services/gui/icon.c similarity index 100% rename from applications/gui/icon.c rename to applications/services/gui/icon.c diff --git a/applications/gui/icon.h b/applications/services/gui/icon.h similarity index 100% rename from applications/gui/icon.h rename to applications/services/gui/icon.h diff --git a/applications/gui/icon_animation.c b/applications/services/gui/icon_animation.c similarity index 100% rename from applications/gui/icon_animation.c rename to applications/services/gui/icon_animation.c diff --git a/applications/gui/icon_animation.h b/applications/services/gui/icon_animation.h similarity index 100% rename from applications/gui/icon_animation.h rename to applications/services/gui/icon_animation.h diff --git a/applications/gui/icon_animation_i.h b/applications/services/gui/icon_animation_i.h similarity index 100% rename from applications/gui/icon_animation_i.h rename to applications/services/gui/icon_animation_i.h diff --git a/applications/gui/icon_i.h b/applications/services/gui/icon_i.h similarity index 100% rename from applications/gui/icon_i.h rename to applications/services/gui/icon_i.h diff --git a/applications/gui/modules/button_menu.c b/applications/services/gui/modules/button_menu.c similarity index 100% rename from applications/gui/modules/button_menu.c rename to applications/services/gui/modules/button_menu.c diff --git a/applications/gui/modules/button_menu.h b/applications/services/gui/modules/button_menu.h similarity index 100% rename from applications/gui/modules/button_menu.h rename to applications/services/gui/modules/button_menu.h diff --git a/applications/gui/modules/button_panel.c b/applications/services/gui/modules/button_panel.c similarity index 99% rename from applications/gui/modules/button_panel.c rename to applications/services/gui/modules/button_panel.c index e3ae59a3..c823e4b1 100644 --- a/applications/gui/modules/button_panel.c +++ b/applications/services/gui/modules/button_panel.c @@ -133,6 +133,8 @@ void button_panel_reset(ButtonPanel* button_panel) { } model->reserve_x = 0; model->reserve_y = 0; + model->selected_item_x = 0; + model->selected_item_y = 0; LabelList_reset(model->labels); ButtonMatrix_reset(model->button_matrix); return true; diff --git a/applications/gui/modules/button_panel.h b/applications/services/gui/modules/button_panel.h similarity index 100% rename from applications/gui/modules/button_panel.h rename to applications/services/gui/modules/button_panel.h diff --git a/applications/gui/modules/byte_input.c b/applications/services/gui/modules/byte_input.c similarity index 100% rename from applications/gui/modules/byte_input.c rename to applications/services/gui/modules/byte_input.c diff --git a/applications/gui/modules/byte_input.h b/applications/services/gui/modules/byte_input.h similarity index 100% rename from applications/gui/modules/byte_input.h rename to applications/services/gui/modules/byte_input.h diff --git a/applications/gui/modules/dialog_ex.c b/applications/services/gui/modules/dialog_ex.c similarity index 100% rename from applications/gui/modules/dialog_ex.c rename to applications/services/gui/modules/dialog_ex.c diff --git a/applications/gui/modules/dialog_ex.h b/applications/services/gui/modules/dialog_ex.h similarity index 100% rename from applications/gui/modules/dialog_ex.h rename to applications/services/gui/modules/dialog_ex.h diff --git a/applications/gui/modules/empty_screen.c b/applications/services/gui/modules/empty_screen.c similarity index 100% rename from applications/gui/modules/empty_screen.c rename to applications/services/gui/modules/empty_screen.c diff --git a/applications/gui/modules/empty_screen.h b/applications/services/gui/modules/empty_screen.h similarity index 100% rename from applications/gui/modules/empty_screen.h rename to applications/services/gui/modules/empty_screen.h diff --git a/applications/gui/modules/file_browser.c b/applications/services/gui/modules/file_browser.c similarity index 85% rename from applications/gui/modules/file_browser.c rename to applications/services/gui/modules/file_browser.c index a987eb1e..1c0c8c74 100644 --- a/applications/gui/modules/file_browser.c +++ b/applications/services/gui/modules/file_browser.c @@ -16,7 +16,9 @@ #define FRAME_HEIGHT 12 #define Y_OFFSET 3 -#define ITEM_LIST_LEN_MAX 100 +#define ITEM_LIST_LEN_MAX 50 + +#define CUSTOM_ICON_MAX_SIZE 32 typedef enum { BrowserItemTypeLoading, @@ -28,25 +30,47 @@ typedef enum { typedef struct { string_t path; BrowserItemType type; + uint8_t* custom_icon_data; + string_t display_name; } BrowserItem_t; static void BrowserItem_t_init(BrowserItem_t* obj) { obj->type = BrowserItemTypeLoading; string_init(obj->path); + string_init(obj->display_name); + obj->custom_icon_data = NULL; } static void BrowserItem_t_init_set(BrowserItem_t* obj, const BrowserItem_t* src) { obj->type = src->type; string_init_set(obj->path, src->path); + string_init_set(obj->display_name, src->display_name); + if(src->custom_icon_data) { + obj->custom_icon_data = malloc(CUSTOM_ICON_MAX_SIZE); + memcpy(obj->custom_icon_data, src->custom_icon_data, CUSTOM_ICON_MAX_SIZE); + } else { + obj->custom_icon_data = NULL; + } } static void BrowserItem_t_set(BrowserItem_t* obj, const BrowserItem_t* src) { obj->type = src->type; string_set(obj->path, src->path); + string_set(obj->display_name, src->display_name); + if(src->custom_icon_data) { + obj->custom_icon_data = malloc(CUSTOM_ICON_MAX_SIZE); + memcpy(obj->custom_icon_data, src->custom_icon_data, CUSTOM_ICON_MAX_SIZE); + } else { + obj->custom_icon_data = NULL; + } } static void BrowserItem_t_clear(BrowserItem_t* obj) { string_clear(obj->path); + string_clear(obj->display_name); + if(obj->custom_icon_data) { + free(obj->custom_icon_data); + } } ARRAY_DEF( @@ -62,10 +86,14 @@ struct FileBrowser { BrowserWorker* worker; const char* ext_filter; bool skip_assets; + bool hide_ext; FileBrowserCallback callback; void* context; + FileBrowserLoadItemCallback item_callback; + void* item_context; + string_ptr result_path; }; @@ -148,6 +176,7 @@ void file_browser_configure( browser->ext_filter = extension; browser->skip_assets = skip_assets; + browser->hide_ext = hide_ext; with_view_model( browser->view, (FileBrowserModel * model) { @@ -186,6 +215,14 @@ void file_browser_set_callback(FileBrowser* browser, FileBrowserCallback callbac browser->callback = callback; } +void file_browser_set_item_callback( + FileBrowser* browser, + FileBrowserLoadItemCallback callback, + void* context) { + browser->item_context = context; + browser->item_callback = callback; +} + static bool browser_is_item_in_array(FileBrowserModel* model, uint32_t idx) { size_t array_size = items_array_size(model->items); @@ -304,18 +341,43 @@ static void browser_list_item_cb(void* context, string_t item_path, bool is_fold FileBrowser* browser = (FileBrowser*)context; BrowserItem_t item; + item.custom_icon_data = NULL; if(!is_last) { - BrowserItem_t_init(&item); - string_set(item.path, item_path); - item.type = (is_folder) ? BrowserItemTypeFolder : BrowserItemTypeFile; + string_init_set(item.path, item_path); + string_init(item.display_name); + if(is_folder) { + item.type = BrowserItemTypeFolder; + } else { + item.type = BrowserItemTypeFile; + if(browser->item_callback) { + item.custom_icon_data = malloc(CUSTOM_ICON_MAX_SIZE); + if(!browser->item_callback( + item_path, + browser->item_context, + &item.custom_icon_data, + item.display_name)) { + free(item.custom_icon_data); + item.custom_icon_data = NULL; + } + } + } + + if(string_empty_p(item.display_name)) { + path_extract_filename( + item_path, + item.display_name, + (browser->hide_ext) && (item.type == BrowserItemTypeFile)); + } with_view_model( browser->view, (FileBrowserModel * model) { items_array_push_back(model->items, item); - return false; + // TODO: calculate if element is visible + return true; }); - BrowserItem_t_clear(&item); + string_clear(item.display_name); + string_clear(item.path); } else { with_view_model( browser->view, (FileBrowserModel * model) { @@ -372,13 +434,16 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) { int32_t idx = CLAMP((uint32_t)(i + model->list_offset), model->item_cnt, 0u); BrowserItemType item_type = BrowserItemTypeLoading; + uint8_t* custom_icon_data = NULL; if(browser_is_item_in_array(model, idx)) { BrowserItem_t* item = items_array_get( model->items, CLAMP(idx - model->array_offset, (int32_t)(array_size - 1), 0)); item_type = item->type; - path_extract_filename( - item->path, filename, (model->hide_ext) && (item_type == BrowserItemTypeFile)); + string_set(filename, item->display_name); + if(item_type == BrowserItemTypeFile) { + custom_icon_data = item->custom_icon_data; + } } else { string_set_str(filename, "---"); } @@ -396,7 +461,11 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) { canvas_set_color(canvas, ColorBlack); } - if((item_type == BrowserItemTypeFile) && (model->file_icon)) { + if(custom_icon_data) { + // Currently only 10*10 icons are supported + canvas_draw_bitmap( + canvas, 2, Y_OFFSET + 1 + i * FRAME_HEIGHT, 10, 10, custom_icon_data); + } else if((item_type == BrowserItemTypeFile) && (model->file_icon)) { canvas_draw_icon(canvas, 2, Y_OFFSET + 1 + i * FRAME_HEIGHT, model->file_icon); } else if(BrowserItemIcons[item_type] != NULL) { canvas_draw_icon( diff --git a/applications/gui/modules/file_browser.h b/applications/services/gui/modules/file_browser.h similarity index 76% rename from applications/gui/modules/file_browser.h rename to applications/services/gui/modules/file_browser.h index ebc64509..57a9f096 100644 --- a/applications/gui/modules/file_browser.h +++ b/applications/services/gui/modules/file_browser.h @@ -15,6 +15,9 @@ extern "C" { typedef struct FileBrowser FileBrowser; typedef void (*FileBrowserCallback)(void* context); +typedef bool ( + *FileBrowserLoadItemCallback)(string_t path, void* context, uint8_t** icon, string_t item_name); + FileBrowser* file_browser_alloc(string_ptr result_path); void file_browser_free(FileBrowser* browser); @@ -34,6 +37,11 @@ void file_browser_stop(FileBrowser* browser); void file_browser_set_callback(FileBrowser* browser, FileBrowserCallback callback, void* context); +void file_browser_set_item_callback( + FileBrowser* browser, + FileBrowserLoadItemCallback callback, + void* context); + #ifdef __cplusplus } #endif diff --git a/applications/gui/modules/file_browser_worker.c b/applications/services/gui/modules/file_browser_worker.c similarity index 100% rename from applications/gui/modules/file_browser_worker.c rename to applications/services/gui/modules/file_browser_worker.c diff --git a/applications/gui/modules/file_browser_worker.h b/applications/services/gui/modules/file_browser_worker.h similarity index 100% rename from applications/gui/modules/file_browser_worker.h rename to applications/services/gui/modules/file_browser_worker.h diff --git a/applications/gui/modules/loading.c b/applications/services/gui/modules/loading.c similarity index 100% rename from applications/gui/modules/loading.c rename to applications/services/gui/modules/loading.c diff --git a/applications/gui/modules/loading.h b/applications/services/gui/modules/loading.h similarity index 100% rename from applications/gui/modules/loading.h rename to applications/services/gui/modules/loading.h diff --git a/applications/gui/modules/menu.c b/applications/services/gui/modules/menu.c similarity index 100% rename from applications/gui/modules/menu.c rename to applications/services/gui/modules/menu.c diff --git a/applications/gui/modules/menu.h b/applications/services/gui/modules/menu.h similarity index 100% rename from applications/gui/modules/menu.h rename to applications/services/gui/modules/menu.h diff --git a/applications/gui/modules/popup.c b/applications/services/gui/modules/popup.c similarity index 100% rename from applications/gui/modules/popup.c rename to applications/services/gui/modules/popup.c diff --git a/applications/gui/modules/popup.h b/applications/services/gui/modules/popup.h similarity index 100% rename from applications/gui/modules/popup.h rename to applications/services/gui/modules/popup.h diff --git a/applications/gui/modules/submenu.c b/applications/services/gui/modules/submenu.c similarity index 100% rename from applications/gui/modules/submenu.c rename to applications/services/gui/modules/submenu.c diff --git a/applications/gui/modules/submenu.h b/applications/services/gui/modules/submenu.h similarity index 100% rename from applications/gui/modules/submenu.h rename to applications/services/gui/modules/submenu.h diff --git a/applications/gui/modules/text_box.c b/applications/services/gui/modules/text_box.c similarity index 100% rename from applications/gui/modules/text_box.c rename to applications/services/gui/modules/text_box.c diff --git a/applications/gui/modules/text_box.h b/applications/services/gui/modules/text_box.h similarity index 100% rename from applications/gui/modules/text_box.h rename to applications/services/gui/modules/text_box.h diff --git a/applications/gui/modules/text_input.c b/applications/services/gui/modules/text_input.c similarity index 99% rename from applications/gui/modules/text_input.c rename to applications/services/gui/modules/text_input.c index 26f74e7a..b8098a3b 100644 --- a/applications/gui/modules/text_input.c +++ b/applications/services/gui/modules/text_input.c @@ -463,8 +463,6 @@ void text_input_free(TextInput* text_input) { // Send stop command furi_timer_stop(text_input->timer); - // Wait till timer stop - while(furi_timer_is_running(text_input->timer)) furi_delay_tick(1); // Release allocated memory furi_timer_free(text_input->timer); diff --git a/applications/gui/modules/text_input.h b/applications/services/gui/modules/text_input.h similarity index 100% rename from applications/gui/modules/text_input.h rename to applications/services/gui/modules/text_input.h diff --git a/applications/gui/modules/validators.c b/applications/services/gui/modules/validators.c similarity index 92% rename from applications/gui/modules/validators.c rename to applications/services/gui/modules/validators.c index ac293f8c..d5fb0fa2 100644 --- a/applications/gui/modules/validators.c +++ b/applications/services/gui/modules/validators.c @@ -1,6 +1,6 @@ #include #include "validators.h" -#include "applications/storage/storage.h" +#include struct ValidatorIsFile { char* app_path_folder; @@ -42,7 +42,9 @@ ValidatorIsFile* validator_is_file_alloc_init( instance->app_path_folder = strdup(app_path_folder); instance->app_extension = app_extension; - instance->current_name = strdup(current_name); + if(current_name != NULL) { + instance->current_name = strdup(current_name); + } return instance; } diff --git a/applications/gui/modules/validators.h b/applications/services/gui/modules/validators.h similarity index 100% rename from applications/gui/modules/validators.h rename to applications/services/gui/modules/validators.h diff --git a/applications/gui/modules/variable_item_list.c b/applications/services/gui/modules/variable_item_list.c similarity index 100% rename from applications/gui/modules/variable_item_list.c rename to applications/services/gui/modules/variable_item_list.c diff --git a/applications/gui/modules/variable_item_list.h b/applications/services/gui/modules/variable_item_list.h similarity index 100% rename from applications/gui/modules/variable_item_list.h rename to applications/services/gui/modules/variable_item_list.h diff --git a/applications/gui/modules/widget.c b/applications/services/gui/modules/widget.c similarity index 99% rename from applications/gui/modules/widget.c rename to applications/services/gui/modules/widget.c index b37a6470..802f76e2 100644 --- a/applications/gui/modules/widget.c +++ b/applications/services/gui/modules/widget.c @@ -1,6 +1,7 @@ #include #include "widget.h" #include +#include "widget_elements/widget_element_i.h" ARRAY_DEF(ElementArray, WidgetElement*, M_PTR_OPLIST); diff --git a/applications/gui/modules/widget.h b/applications/services/gui/modules/widget.h similarity index 98% rename from applications/gui/modules/widget.h rename to applications/services/gui/modules/widget.h index 03586165..50c26175 100644 --- a/applications/gui/modules/widget.h +++ b/applications/services/gui/modules/widget.h @@ -4,8 +4,8 @@ */ #pragma once - -#include "widget_elements/widget_element_i.h" +#include +#include "widget_elements/widget_element.h" #ifdef __cplusplus extern "C" { diff --git a/applications/services/gui/modules/widget_elements/widget_element.h b/applications/services/gui/modules/widget_elements/widget_element.h new file mode 100644 index 00000000..67990417 --- /dev/null +++ b/applications/services/gui/modules/widget_elements/widget_element.h @@ -0,0 +1,22 @@ +/** + * @file widget_element_i.h + * GUI: internal Widget Element API + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + GuiButtonTypeLeft, + GuiButtonTypeCenter, + GuiButtonTypeRight, +} GuiButtonType; + +typedef void (*ButtonCallback)(GuiButtonType result, InputType type, void* context); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/applications/gui/modules/widget_elements/widget_element_button.c b/applications/services/gui/modules/widget_elements/widget_element_button.c similarity index 100% rename from applications/gui/modules/widget_elements/widget_element_button.c rename to applications/services/gui/modules/widget_elements/widget_element_button.c diff --git a/applications/gui/modules/widget_elements/widget_element_frame.c b/applications/services/gui/modules/widget_elements/widget_element_frame.c similarity index 100% rename from applications/gui/modules/widget_elements/widget_element_frame.c rename to applications/services/gui/modules/widget_elements/widget_element_frame.c diff --git a/applications/gui/modules/widget_elements/widget_element_i.h b/applications/services/gui/modules/widget_elements/widget_element_i.h similarity index 90% rename from applications/gui/modules/widget_elements/widget_element_i.h rename to applications/services/gui/modules/widget_elements/widget_element_i.h index 316ed740..67dea4b1 100644 --- a/applications/gui/modules/widget_elements/widget_element_i.h +++ b/applications/services/gui/modules/widget_elements/widget_element_i.h @@ -7,14 +7,11 @@ #include #include #include +#include "widget_element.h" -typedef enum { - GuiButtonTypeLeft, - GuiButtonTypeCenter, - GuiButtonTypeRight, -} GuiButtonType; - -typedef void (*ButtonCallback)(GuiButtonType result, InputType type, void* context); +#ifdef __cplusplus +extern "C" { +#endif typedef struct WidgetElement WidgetElement; typedef struct Widget Widget; @@ -88,3 +85,7 @@ WidgetElement* widget_element_text_scroll_create( uint8_t width, uint8_t height, const char* text); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/applications/gui/modules/widget_elements/widget_element_icon.c b/applications/services/gui/modules/widget_elements/widget_element_icon.c similarity index 100% rename from applications/gui/modules/widget_elements/widget_element_icon.c rename to applications/services/gui/modules/widget_elements/widget_element_icon.c diff --git a/applications/gui/modules/widget_elements/widget_element_string.c b/applications/services/gui/modules/widget_elements/widget_element_string.c similarity index 100% rename from applications/gui/modules/widget_elements/widget_element_string.c rename to applications/services/gui/modules/widget_elements/widget_element_string.c diff --git a/applications/gui/modules/widget_elements/widget_element_string_multiline.c b/applications/services/gui/modules/widget_elements/widget_element_string_multiline.c similarity index 100% rename from applications/gui/modules/widget_elements/widget_element_string_multiline.c rename to applications/services/gui/modules/widget_elements/widget_element_string_multiline.c diff --git a/applications/gui/modules/widget_elements/widget_element_text_box.c b/applications/services/gui/modules/widget_elements/widget_element_text_box.c similarity index 100% rename from applications/gui/modules/widget_elements/widget_element_text_box.c rename to applications/services/gui/modules/widget_elements/widget_element_text_box.c diff --git a/applications/gui/modules/widget_elements/widget_element_text_scroll.c b/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c similarity index 100% rename from applications/gui/modules/widget_elements/widget_element_text_scroll.c rename to applications/services/gui/modules/widget_elements/widget_element_text_scroll.c diff --git a/applications/gui/scene_manager.c b/applications/services/gui/scene_manager.c similarity index 100% rename from applications/gui/scene_manager.c rename to applications/services/gui/scene_manager.c diff --git a/applications/gui/scene_manager.h b/applications/services/gui/scene_manager.h similarity index 100% rename from applications/gui/scene_manager.h rename to applications/services/gui/scene_manager.h diff --git a/applications/gui/scene_manager_i.h b/applications/services/gui/scene_manager_i.h similarity index 100% rename from applications/gui/scene_manager_i.h rename to applications/services/gui/scene_manager_i.h diff --git a/applications/gui/view.c b/applications/services/gui/view.c similarity index 100% rename from applications/gui/view.c rename to applications/services/gui/view.c diff --git a/applications/gui/view.h b/applications/services/gui/view.h similarity index 100% rename from applications/gui/view.h rename to applications/services/gui/view.h diff --git a/applications/gui/view_dispatcher.c b/applications/services/gui/view_dispatcher.c similarity index 100% rename from applications/gui/view_dispatcher.c rename to applications/services/gui/view_dispatcher.c diff --git a/applications/gui/view_dispatcher.h b/applications/services/gui/view_dispatcher.h similarity index 100% rename from applications/gui/view_dispatcher.h rename to applications/services/gui/view_dispatcher.h diff --git a/applications/gui/view_dispatcher_i.h b/applications/services/gui/view_dispatcher_i.h similarity index 100% rename from applications/gui/view_dispatcher_i.h rename to applications/services/gui/view_dispatcher_i.h diff --git a/applications/gui/view_i.h b/applications/services/gui/view_i.h similarity index 100% rename from applications/gui/view_i.h rename to applications/services/gui/view_i.h diff --git a/applications/gui/view_port.c b/applications/services/gui/view_port.c similarity index 100% rename from applications/gui/view_port.c rename to applications/services/gui/view_port.c diff --git a/applications/gui/view_port.h b/applications/services/gui/view_port.h similarity index 100% rename from applications/gui/view_port.h rename to applications/services/gui/view_port.h diff --git a/applications/gui/view_port_i.h b/applications/services/gui/view_port_i.h similarity index 100% rename from applications/gui/view_port_i.h rename to applications/services/gui/view_port_i.h diff --git a/applications/gui/view_stack.c b/applications/services/gui/view_stack.c similarity index 100% rename from applications/gui/view_stack.c rename to applications/services/gui/view_stack.c diff --git a/applications/gui/view_stack.h b/applications/services/gui/view_stack.h similarity index 100% rename from applications/gui/view_stack.h rename to applications/services/gui/view_stack.h diff --git a/applications/input/application.fam b/applications/services/input/application.fam similarity index 86% rename from applications/input/application.fam rename to applications/services/input/application.fam index 545630e6..d344fc35 100644 --- a/applications/input/application.fam +++ b/applications/services/input/application.fam @@ -6,4 +6,5 @@ App( cdefines=["SRV_INPUT"], stack_size=1 * 1024, order=80, + sdk_headers=["input.h"], ) diff --git a/applications/input/input.c b/applications/services/input/input.c similarity index 100% rename from applications/input/input.c rename to applications/services/input/input.c diff --git a/applications/input/input.h b/applications/services/input/input.h similarity index 94% rename from applications/input/input.h rename to applications/services/input/input.h index 001ab1e2..bd0ba390 100644 --- a/applications/input/input.h +++ b/applications/services/input/input.h @@ -7,6 +7,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + #define RECORD_INPUT_EVENTS "input_events" /** Input Types @@ -38,3 +42,7 @@ const char* input_get_key_name(InputKey key); * @return string */ const char* input_get_type_name(InputType type); + +#ifdef __cplusplus +} +#endif diff --git a/applications/input/input_cli.c b/applications/services/input/input_cli.c similarity index 100% rename from applications/input/input_cli.c rename to applications/services/input/input_cli.c diff --git a/applications/input/input_i.h b/applications/services/input/input_i.h similarity index 100% rename from applications/input/input_i.h rename to applications/services/input/input_i.h diff --git a/applications/loader/application.fam b/applications/services/loader/application.fam similarity index 87% rename from applications/loader/application.fam rename to applications/services/loader/application.fam index c1ba4e54..91103e46 100644 --- a/applications/loader/application.fam +++ b/applications/services/loader/application.fam @@ -7,4 +7,5 @@ App( requires=["gui"], stack_size=2 * 1024, order=90, + sdk_headers=["loader.h"], ) diff --git a/applications/loader/loader.c b/applications/services/loader/loader.c similarity index 99% rename from applications/loader/loader.c rename to applications/services/loader/loader.c index 9ece7f27..cf7e5a10 100644 --- a/applications/loader/loader.c +++ b/applications/services/loader/loader.c @@ -388,7 +388,7 @@ static void loader_build_menu() { loader_submenu_callback, (void*)LoaderMenuViewPlugins); } - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug) && (FLIPPER_DEBUG_APPS_COUNT > 0)) { menu_add_item( loader_instance->primary_menu, "Debug Tools", diff --git a/applications/loader/loader.h b/applications/services/loader/loader.h similarity index 93% rename from applications/loader/loader.h rename to applications/services/loader/loader.h index 8f95d81b..954e79c5 100644 --- a/applications/loader/loader.h +++ b/applications/services/loader/loader.h @@ -3,6 +3,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define RECORD_LOADER "loader" typedef struct Loader Loader; @@ -49,3 +53,7 @@ void loader_update_menu(); /** Show primary loader */ FuriPubSub* loader_get_pubsub(Loader* instance); + +#ifdef __cplusplus +} +#endif diff --git a/applications/loader/loader_i.h b/applications/services/loader/loader_i.h similarity index 100% rename from applications/loader/loader_i.h rename to applications/services/loader/loader_i.h diff --git a/applications/notification/application.fam b/applications/services/notification/application.fam similarity index 54% rename from applications/notification/application.fam rename to applications/services/notification/application.fam index be730d51..82f94085 100644 --- a/applications/notification/application.fam +++ b/applications/services/notification/application.fam @@ -8,14 +8,5 @@ App( provides=["notification_settings"], stack_size=int(1.5 * 1024), order=100, -) - -App( - appid="notification_settings", - name="LCD and Notifications", - apptype=FlipperAppType.SETTINGS, - entry_point="notification_settings_app", - requires=["notification"], - stack_size=1 * 1024, - order=20, + sdk_headers=["notification.h", "notification_messages.h"], ) diff --git a/applications/notification/notification.h b/applications/services/notification/notification.h similarity index 100% rename from applications/notification/notification.h rename to applications/services/notification/notification.h diff --git a/applications/notification/notification_app.c b/applications/services/notification/notification_app.c similarity index 100% rename from applications/notification/notification_app.c rename to applications/services/notification/notification_app.c diff --git a/applications/notification/notification_app.h b/applications/services/notification/notification_app.h similarity index 100% rename from applications/notification/notification_app.h rename to applications/services/notification/notification_app.h diff --git a/applications/notification/notification_app_api.c b/applications/services/notification/notification_app_api.c similarity index 100% rename from applications/notification/notification_app_api.c rename to applications/services/notification/notification_app_api.c diff --git a/applications/notification/notification_messages.c b/applications/services/notification/notification_messages.c similarity index 100% rename from applications/notification/notification_messages.c rename to applications/services/notification/notification_messages.c diff --git a/applications/notification/notification_messages.h b/applications/services/notification/notification_messages.h similarity index 100% rename from applications/notification/notification_messages.h rename to applications/services/notification/notification_messages.h diff --git a/applications/notification/notification_messages_notes.c b/applications/services/notification/notification_messages_notes.c similarity index 100% rename from applications/notification/notification_messages_notes.c rename to applications/services/notification/notification_messages_notes.c diff --git a/applications/notification/notification_messages_notes.h b/applications/services/notification/notification_messages_notes.h similarity index 100% rename from applications/notification/notification_messages_notes.h rename to applications/services/notification/notification_messages_notes.h diff --git a/applications/notification/notification_settings_filename.h b/applications/services/notification/notification_settings_filename.h similarity index 100% rename from applications/notification/notification_settings_filename.h rename to applications/services/notification/notification_settings_filename.h diff --git a/applications/services/power/application.fam b/applications/services/power/application.fam new file mode 100644 index 00000000..f14d88c5 --- /dev/null +++ b/applications/services/power/application.fam @@ -0,0 +1,26 @@ +App( + appid="power", + name="PowerSrv", + apptype=FlipperAppType.SERVICE, + entry_point="power_srv", + cdefines=["SRV_POWER"], + requires=[ + "gui", + "cli", + ], + provides=[ + "power_settings", + "power_start", + ], + stack_size=1 * 1024, + order=110, + sdk_headers=["power_service/power.h"], +) + +App( + appid="power_start", + apptype=FlipperAppType.STARTUP, + entry_point="power_on_system_start", + requires=["power"], + order=80, +) diff --git a/applications/power/power_cli.c b/applications/services/power/power_cli.c similarity index 100% rename from applications/power/power_cli.c rename to applications/services/power/power_cli.c diff --git a/applications/services/power/power_cli.h b/applications/services/power/power_cli.h new file mode 100644 index 00000000..1517c614 --- /dev/null +++ b/applications/services/power/power_cli.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void power_on_system_start(); + +#ifdef __cplusplus +} +#endif diff --git a/applications/power/power_service/power.c b/applications/services/power/power_service/power.c similarity index 98% rename from applications/power/power_service/power.c rename to applications/services/power/power_service/power.c index 3a2c6cf3..85d217f2 100644 --- a/applications/power/power_service/power.c +++ b/applications/services/power/power_service/power.c @@ -127,6 +127,7 @@ static void power_check_charging_state(Power* power) { static bool power_update_info(Power* power) { PowerInfo info; + info.is_charging = furi_hal_power_is_charging(); info.gauge_is_ok = furi_hal_power_gauge_is_ok(); info.charge = furi_hal_power_get_pct(); info.health = furi_hal_power_get_bat_health_pct(); @@ -142,6 +143,7 @@ static bool power_update_info(Power* power) { furi_mutex_acquire(power->api_mtx, FuriWaitForever); bool need_refresh = power->info.charge != info.charge; + need_refresh |= power->info.is_charging != info.is_charging; power->info = info; furi_mutex_release(power->api_mtx); diff --git a/applications/power/power_service/power.h b/applications/services/power/power_service/power.h similarity index 95% rename from applications/power/power_service/power.h rename to applications/services/power/power_service/power.h index c516f28f..bdf5fa52 100644 --- a/applications/power/power_service/power.h +++ b/applications/services/power/power_service/power.h @@ -4,6 +4,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define RECORD_POWER "power" typedef struct Power Power; @@ -32,6 +36,7 @@ typedef struct { typedef struct { bool gauge_is_ok; + bool is_charging; float current_charger; float current_gauge; @@ -87,3 +92,7 @@ bool power_is_battery_healthy(Power* power); * @param enable true - enable, false - disable */ void power_enable_low_battery_level_notification(Power* power, bool enable); + +#ifdef __cplusplus +} +#endif diff --git a/applications/power/power_service/power_api.c b/applications/services/power/power_service/power_api.c similarity index 100% rename from applications/power/power_service/power_api.c rename to applications/services/power/power_service/power_api.c diff --git a/applications/power/power_service/power_i.h b/applications/services/power/power_service/power_i.h similarity index 100% rename from applications/power/power_service/power_i.h rename to applications/services/power/power_service/power_i.h diff --git a/applications/power/power_service/views/power_off.c b/applications/services/power/power_service/views/power_off.c similarity index 100% rename from applications/power/power_service/views/power_off.c rename to applications/services/power/power_service/views/power_off.c diff --git a/applications/power/power_service/views/power_off.h b/applications/services/power/power_service/views/power_off.h similarity index 100% rename from applications/power/power_service/views/power_off.h rename to applications/services/power/power_service/views/power_off.h diff --git a/applications/power/power_service/views/power_unplug_usb.c b/applications/services/power/power_service/views/power_unplug_usb.c similarity index 100% rename from applications/power/power_service/views/power_unplug_usb.c rename to applications/services/power/power_service/views/power_unplug_usb.c diff --git a/applications/power/power_service/views/power_unplug_usb.h b/applications/services/power/power_service/views/power_unplug_usb.h similarity index 100% rename from applications/power/power_service/views/power_unplug_usb.h rename to applications/services/power/power_service/views/power_unplug_usb.h diff --git a/applications/rpc/application.fam b/applications/services/rpc/application.fam similarity index 84% rename from applications/rpc/application.fam rename to applications/services/rpc/application.fam index 3a139cb3..7c0b6813 100644 --- a/applications/rpc/application.fam +++ b/applications/services/rpc/application.fam @@ -5,4 +5,5 @@ App( cdefines=["SRV_RPC"], requires=["cli"], order=10, + sdk_headers=["rpc_app.h"], ) diff --git a/applications/rpc/rpc.c b/applications/services/rpc/rpc.c similarity index 100% rename from applications/rpc/rpc.c rename to applications/services/rpc/rpc.c diff --git a/applications/rpc/rpc.h b/applications/services/rpc/rpc.h similarity index 98% rename from applications/rpc/rpc.h rename to applications/services/rpc/rpc.h index dea8b749..40493949 100644 --- a/applications/rpc/rpc.h +++ b/applications/services/rpc/rpc.h @@ -5,6 +5,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define RPC_BUFFER_SIZE (1024) #define RPC_MAX_MESSAGE_SIZE (1536) @@ -114,3 +118,7 @@ size_t rpc_session_feed(RpcSession* session, uint8_t* buffer, size_t size, TickT * @return bytes available in buffer */ size_t rpc_session_get_available_size(RpcSession* session); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/applications/rpc/rpc_app.c b/applications/services/rpc/rpc_app.c similarity index 100% rename from applications/rpc/rpc_app.c rename to applications/services/rpc/rpc_app.c diff --git a/applications/rpc/rpc_app.h b/applications/services/rpc/rpc_app.h similarity index 100% rename from applications/rpc/rpc_app.h rename to applications/services/rpc/rpc_app.h diff --git a/applications/rpc/rpc_cli.c b/applications/services/rpc/rpc_cli.c similarity index 100% rename from applications/rpc/rpc_cli.c rename to applications/services/rpc/rpc_cli.c diff --git a/applications/rpc/rpc_debug.c b/applications/services/rpc/rpc_debug.c similarity index 100% rename from applications/rpc/rpc_debug.c rename to applications/services/rpc/rpc_debug.c diff --git a/applications/rpc/rpc_gpio.c b/applications/services/rpc/rpc_gpio.c similarity index 100% rename from applications/rpc/rpc_gpio.c rename to applications/services/rpc/rpc_gpio.c diff --git a/applications/rpc/rpc_gui.c b/applications/services/rpc/rpc_gui.c similarity index 100% rename from applications/rpc/rpc_gui.c rename to applications/services/rpc/rpc_gui.c diff --git a/applications/rpc/rpc_i.h b/applications/services/rpc/rpc_i.h similarity index 100% rename from applications/rpc/rpc_i.h rename to applications/services/rpc/rpc_i.h diff --git a/applications/rpc/rpc_storage.c b/applications/services/rpc/rpc_storage.c similarity index 100% rename from applications/rpc/rpc_storage.c rename to applications/services/rpc/rpc_storage.c diff --git a/applications/rpc/rpc_system.c b/applications/services/rpc/rpc_system.c similarity index 100% rename from applications/rpc/rpc_system.c rename to applications/services/rpc/rpc_system.c diff --git a/applications/storage/application.fam b/applications/services/storage/application.fam similarity index 92% rename from applications/storage/application.fam rename to applications/services/storage/application.fam index 21089635..7aa721cc 100644 --- a/applications/storage/application.fam +++ b/applications/services/storage/application.fam @@ -8,6 +8,7 @@ App( provides=["storage_start"], stack_size=3 * 1024, order=120, + sdk_headers=["storage.h"], ) App( diff --git a/applications/storage/filesystem_api.c b/applications/services/storage/filesystem_api.c similarity index 100% rename from applications/storage/filesystem_api.c rename to applications/services/storage/filesystem_api.c diff --git a/applications/storage/filesystem_api_defines.h b/applications/services/storage/filesystem_api_defines.h similarity index 100% rename from applications/storage/filesystem_api_defines.h rename to applications/services/storage/filesystem_api_defines.h diff --git a/applications/storage/filesystem_api_internal.h b/applications/services/storage/filesystem_api_internal.h similarity index 100% rename from applications/storage/filesystem_api_internal.h rename to applications/services/storage/filesystem_api_internal.h diff --git a/applications/storage/storage.c b/applications/services/storage/storage.c similarity index 100% rename from applications/storage/storage.c rename to applications/services/storage/storage.c diff --git a/applications/storage/storage.h b/applications/services/storage/storage.h similarity index 100% rename from applications/storage/storage.h rename to applications/services/storage/storage.h diff --git a/applications/storage/storage_cli.c b/applications/services/storage/storage_cli.c similarity index 100% rename from applications/storage/storage_cli.c rename to applications/services/storage/storage_cli.c diff --git a/applications/storage/storage_external_api.c b/applications/services/storage/storage_external_api.c similarity index 100% rename from applications/storage/storage_external_api.c rename to applications/services/storage/storage_external_api.c diff --git a/applications/storage/storage_glue.c b/applications/services/storage/storage_glue.c similarity index 100% rename from applications/storage/storage_glue.c rename to applications/services/storage/storage_glue.c diff --git a/applications/storage/storage_glue.h b/applications/services/storage/storage_glue.h similarity index 100% rename from applications/storage/storage_glue.h rename to applications/services/storage/storage_glue.h diff --git a/applications/storage/storage_i.h b/applications/services/storage/storage_i.h similarity index 100% rename from applications/storage/storage_i.h rename to applications/services/storage/storage_i.h diff --git a/applications/storage/storage_internal_api.c b/applications/services/storage/storage_internal_api.c similarity index 100% rename from applications/storage/storage_internal_api.c rename to applications/services/storage/storage_internal_api.c diff --git a/applications/storage/storage_message.h b/applications/services/storage/storage_message.h similarity index 100% rename from applications/storage/storage_message.h rename to applications/services/storage/storage_message.h diff --git a/applications/storage/storage_processing.c b/applications/services/storage/storage_processing.c similarity index 100% rename from applications/storage/storage_processing.c rename to applications/services/storage/storage_processing.c diff --git a/applications/storage/storage_processing.h b/applications/services/storage/storage_processing.h similarity index 100% rename from applications/storage/storage_processing.h rename to applications/services/storage/storage_processing.h diff --git a/applications/storage/storage_sd_api.c b/applications/services/storage/storage_sd_api.c similarity index 100% rename from applications/storage/storage_sd_api.c rename to applications/services/storage/storage_sd_api.c diff --git a/applications/storage/storage_sd_api.h b/applications/services/storage/storage_sd_api.h similarity index 100% rename from applications/storage/storage_sd_api.h rename to applications/services/storage/storage_sd_api.h diff --git a/applications/storage/storage_test_app.c b/applications/services/storage/storage_test_app.c similarity index 100% rename from applications/storage/storage_test_app.c rename to applications/services/storage/storage_test_app.c diff --git a/applications/storage/storages/sd_notify.c b/applications/services/storage/storages/sd_notify.c similarity index 100% rename from applications/storage/storages/sd_notify.c rename to applications/services/storage/storages/sd_notify.c diff --git a/applications/storage/storages/sd_notify.h b/applications/services/storage/storages/sd_notify.h similarity index 100% rename from applications/storage/storages/sd_notify.h rename to applications/services/storage/storages/sd_notify.h diff --git a/applications/storage/storages/storage_ext.c b/applications/services/storage/storages/storage_ext.c similarity index 100% rename from applications/storage/storages/storage_ext.c rename to applications/services/storage/storages/storage_ext.c diff --git a/applications/storage/storages/storage_ext.h b/applications/services/storage/storages/storage_ext.h similarity index 100% rename from applications/storage/storages/storage_ext.h rename to applications/services/storage/storages/storage_ext.h diff --git a/applications/storage/storages/storage_int.c b/applications/services/storage/storages/storage_int.c similarity index 99% rename from applications/storage/storages/storage_int.c rename to applications/services/storage/storages/storage_int.c index 0765a92d..cae61f16 100644 --- a/applications/storage/storages/storage_int.c +++ b/applications/services/storage/storages/storage_int.c @@ -9,7 +9,7 @@ /* When less than LFS_RESERVED_PAGES_COUNT are left free, creation & * modification of non-dot files is restricted */ -#define LFS_RESERVED_PAGES_COUNT 5 +#define LFS_RESERVED_PAGES_COUNT 3 typedef struct { const size_t start_address; diff --git a/applications/storage/storages/storage_int.h b/applications/services/storage/storages/storage_int.h similarity index 100% rename from applications/storage/storages/storage_int.h rename to applications/services/storage/storages/storage_int.h diff --git a/applications/about/about.c b/applications/settings/about/about.c similarity index 100% rename from applications/about/about.c rename to applications/settings/about/about.c diff --git a/applications/about/application.fam b/applications/settings/about/application.fam similarity index 100% rename from applications/about/application.fam rename to applications/settings/about/application.fam diff --git a/applications/settings/application.fam b/applications/settings/application.fam new file mode 100644 index 00000000..cc4b9703 --- /dev/null +++ b/applications/settings/application.fam @@ -0,0 +1,10 @@ +App( + appid="settings_apps", + name="Basic settings apps bundle", + apptype=FlipperAppType.METAPACKAGE, + provides=[ + "passport", + "system_settings", + "about", + ], +) diff --git a/applications/settings/bt_settings_app/application.fam b/applications/settings/bt_settings_app/application.fam new file mode 100644 index 00000000..7a985046 --- /dev/null +++ b/applications/settings/bt_settings_app/application.fam @@ -0,0 +1,12 @@ +App( + appid="bt_settings", + name="Bluetooth", + apptype=FlipperAppType.SETTINGS, + entry_point="bt_settings_app", + stack_size=1 * 1024, + requires=[ + "bt", + "gui", + ], + order=10, +) diff --git a/applications/bt/bt_settings_app/bt_settings_app.c b/applications/settings/bt_settings_app/bt_settings_app.c similarity index 100% rename from applications/bt/bt_settings_app/bt_settings_app.c rename to applications/settings/bt_settings_app/bt_settings_app.c diff --git a/applications/bt/bt_settings_app/bt_settings_app.h b/applications/settings/bt_settings_app/bt_settings_app.h similarity index 96% rename from applications/bt/bt_settings_app/bt_settings_app.h rename to applications/settings/bt_settings_app/bt_settings_app.h index 5b4a8d13..c45ff3db 100644 --- a/applications/bt/bt_settings_app/bt_settings_app.h +++ b/applications/settings/bt_settings_app/bt_settings_app.h @@ -11,7 +11,7 @@ #include #include -#include "../bt_settings.h" +#include #include "scenes/bt_settings_scene.h" enum BtSettingsCustomEvent { diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene.c b/applications/settings/bt_settings_app/scenes/bt_settings_scene.c similarity index 100% rename from applications/bt/bt_settings_app/scenes/bt_settings_scene.c rename to applications/settings/bt_settings_app/scenes/bt_settings_scene.c diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene.h b/applications/settings/bt_settings_app/scenes/bt_settings_scene.h similarity index 100% rename from applications/bt/bt_settings_app/scenes/bt_settings_scene.h rename to applications/settings/bt_settings_app/scenes/bt_settings_scene.h diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h b/applications/settings/bt_settings_app/scenes/bt_settings_scene_config.h similarity index 100% rename from applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h rename to applications/settings/bt_settings_app/scenes/bt_settings_scene_config.h diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c b/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c similarity index 100% rename from applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c rename to applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c b/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c similarity index 100% rename from applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c rename to applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c b/applications/settings/bt_settings_app/scenes/bt_settings_scene_start.c similarity index 100% rename from applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c rename to applications/settings/bt_settings_app/scenes/bt_settings_scene_start.c diff --git a/applications/settings/desktop_settings/application.fam b/applications/settings/desktop_settings/application.fam new file mode 100644 index 00000000..d01a28d3 --- /dev/null +++ b/applications/settings/desktop_settings/application.fam @@ -0,0 +1,12 @@ +App( + appid="desktop_settings", + name="Desktop", + apptype=FlipperAppType.SETTINGS, + entry_point="desktop_settings_app", + requires=[ + "desktop", + "gui", + ], + stack_size=1 * 1024, + order=50, +) diff --git a/applications/desktop/desktop_settings/desktop_settings_app.c b/applications/settings/desktop_settings/desktop_settings_app.c similarity index 97% rename from applications/desktop/desktop_settings/desktop_settings_app.c rename to applications/settings/desktop_settings/desktop_settings_app.c index 89513a8b..a2ed8b72 100644 --- a/applications/desktop/desktop_settings/desktop_settings_app.c +++ b/applications/settings/desktop_settings/desktop_settings_app.c @@ -4,7 +4,7 @@ #include "desktop_settings_app.h" #include "scenes/desktop_settings_scene.h" -#include "../views/desktop_view_pin_input.h" +#include static bool desktop_settings_custom_event_callback(void* context, uint32_t event) { furi_assert(context); @@ -89,7 +89,7 @@ void desktop_settings_app_free(DesktopSettingsApp* app) { extern int32_t desktop_settings_app(void* p) { DesktopSettingsApp* app = desktop_settings_app_alloc(); - LOAD_DESKTOP_SETTINGS(&app->settings); + DESKTOP_SETTINGS_LOAD(&app->settings); if(p && (strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG) == 0)) { scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto); } else { diff --git a/applications/desktop/desktop_settings/desktop_settings_app.h b/applications/settings/desktop_settings/desktop_settings_app.h similarity index 92% rename from applications/desktop/desktop_settings/desktop_settings_app.h rename to applications/settings/desktop_settings/desktop_settings_app.h index 93ca7b35..25c5b3ad 100644 --- a/applications/desktop/desktop_settings/desktop_settings_app.h +++ b/applications/settings/desktop_settings/desktop_settings_app.h @@ -7,8 +7,8 @@ #include #include -#include "desktop_settings.h" -#include "desktop/views/desktop_view_pin_input.h" +#include +#include #include "views/desktop_settings_view_pin_setup_howto.h" #include "views/desktop_settings_view_pin_setup_howto2.h" diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene.c similarity index 100% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene.c rename to applications/settings/desktop_settings/scenes/desktop_settings_scene.c diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene.h b/applications/settings/desktop_settings/scenes/desktop_settings_scene.h similarity index 100% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene.h rename to applications/settings/desktop_settings/scenes/desktop_settings_scene.h diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_config.h b/applications/settings/desktop_settings/scenes/desktop_settings_scene_config.h similarity index 100% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene_config.h rename to applications/settings/desktop_settings/scenes/desktop_settings_scene_config.h diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_favorite.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c similarity index 97% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene_favorite.c rename to applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c index 0ec18af7..d8c579b3 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_favorite.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c @@ -56,6 +56,6 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e void desktop_settings_scene_favorite_on_exit(void* context) { DesktopSettingsApp* app = context; - SAVE_DESKTOP_SETTINGS(&app->settings); + DESKTOP_SETTINGS_SAVE(&app->settings); submenu_reset(app->submenu); } diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_i.h b/applications/settings/desktop_settings/scenes/desktop_settings_scene_i.h similarity index 100% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene_i.h rename to applications/settings/desktop_settings/scenes/desktop_settings_scene_i.h diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_auth.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c similarity index 95% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_auth.c rename to applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c index c43fff6a..5fed235c 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_auth.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c @@ -1,10 +1,10 @@ #include #include #include -#include "../../helpers/pin_lock.h" +#include #include "../desktop_settings_app.h" -#include "desktop/desktop_settings/desktop_settings.h" -#include "desktop/views/desktop_view_pin_input.h" +#include +#include #include "desktop_settings_scene.h" #include "desktop_settings_scene_i.h" @@ -33,7 +33,7 @@ static void pin_auth_back_callback(void* context) { void desktop_settings_scene_pin_auth_on_enter(void* context) { DesktopSettingsApp* app = context; - LOAD_DESKTOP_SETTINGS(&app->settings); + DESKTOP_SETTINGS_LOAD(&app->settings); furi_assert(app->settings.pin_code.length > 0); desktop_view_pin_input_set_context(app->pin_input_view, app); diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_disable.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c similarity index 92% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_disable.c rename to applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c index f6f6b256..7fbcc325 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_disable.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c @@ -4,8 +4,7 @@ #include #include "../desktop_settings_app.h" -#include "../desktop_settings.h" -#include "desktop/desktop_settings/desktop_settings.h" +#include #include "desktop_settings_scene.h" #define SCENE_EVENT_EXIT (0U) @@ -21,7 +20,7 @@ void desktop_settings_scene_pin_disable_on_enter(void* context) { DesktopSettingsApp* app = context; app->settings.pin_code.length = 0; memset(app->settings.pin_code.data, '0', sizeof(app->settings.pin_code.data)); - SAVE_DESKTOP_SETTINGS(&app->settings); + DESKTOP_SETTINGS_SAVE(&app->settings); popup_set_context(app->popup, app); popup_set_callback(app->popup, pin_disable_back_callback); diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_error.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c similarity index 95% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_error.c rename to applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c index 38852dd8..dd1e8579 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_error.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c @@ -2,11 +2,11 @@ #include #include -#include "desktop/desktop_settings/desktop_settings.h" -#include "desktop/views/desktop_view_pin_input.h" +#include +#include #include "desktop_settings_scene.h" #include "desktop_settings_scene_i.h" -#include "../../helpers/pin_lock.h" +#include #include "../desktop_settings_app.h" #define SCENE_EVENT_EXIT (0U) diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_menu.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_menu.c similarity index 100% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_menu.c rename to applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_menu.c diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup.c similarity index 96% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup.c rename to applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup.c index b536a343..bf0f48ae 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup.c @@ -3,11 +3,11 @@ #include #include "../desktop_settings_app.h" -#include "desktop/desktop_settings/desktop_settings.h" -#include "desktop/views/desktop_view_pin_input.h" +#include +#include #include "desktop_settings_scene.h" #include "desktop_settings_scene_i.h" -#include "../../helpers/pin_lock.h" +#include #define SCENE_EVENT_EXIT (0U) #define SCENE_EVENT_1ST_PIN_ENTERED (1U) diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c similarity index 95% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c rename to applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c index 42408428..f6ceb96d 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c @@ -6,8 +6,8 @@ #include #include "../desktop_settings_app.h" -#include "desktop/desktop_settings/desktop_settings.h" -#include "desktop/views/desktop_view_pin_input.h" +#include +#include #include "desktop_settings_scene.h" #define SCENE_EVENT_DONE (0U) @@ -24,7 +24,7 @@ void desktop_settings_scene_pin_setup_done_on_enter(void* context) { DesktopSettingsApp* app = context; app->settings.pin_code = app->pincode_buffer; - SAVE_DESKTOP_SETTINGS(&app->settings); + DESKTOP_SETTINGS_SAVE(&app->settings); NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); notification_message(notification, &sequence_single_vibro); furi_record_close(RECORD_NOTIFICATION); diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c similarity index 100% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c rename to applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c similarity index 100% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c rename to applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c similarity index 98% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c rename to applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index 8e649c69..8530a1a7 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -96,5 +96,5 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even void desktop_settings_scene_start_on_exit(void* context) { DesktopSettingsApp* app = context; variable_item_list_reset(app->variable_item_list); - SAVE_DESKTOP_SETTINGS(&app->settings); + DESKTOP_SETTINGS_SAVE(&app->settings); } diff --git a/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto.c b/applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto.c similarity index 100% rename from applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto.c rename to applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto.c diff --git a/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto.h b/applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto.h similarity index 100% rename from applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto.h rename to applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto.h diff --git a/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto2.c b/applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto2.c similarity index 100% rename from applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto2.c rename to applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto2.c diff --git a/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto2.h b/applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto2.h similarity index 100% rename from applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto2.h rename to applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto2.h diff --git a/applications/dolphin/application.fam b/applications/settings/dolphin_passport/application.fam similarity index 56% rename from applications/dolphin/application.fam rename to applications/settings/dolphin_passport/application.fam index 1ee0e3cf..4167e9dc 100644 --- a/applications/dolphin/application.fam +++ b/applications/settings/dolphin_passport/application.fam @@ -1,13 +1,3 @@ -App( - appid="dolphin", - name="DolphinSrv", - apptype=FlipperAppType.SERVICE, - entry_point="dolphin_srv", - cdefines=["SRV_DOLPHIN"], - stack_size=1 * 1024, - order=50, -) - App( appid="passport", name="Passport", diff --git a/applications/dolphin/passport/passport.c b/applications/settings/dolphin_passport/passport.c similarity index 100% rename from applications/dolphin/passport/passport.c rename to applications/settings/dolphin_passport/passport.c diff --git a/applications/settings/notification_settings/application.fam b/applications/settings/notification_settings/application.fam new file mode 100644 index 00000000..117a8387 --- /dev/null +++ b/applications/settings/notification_settings/application.fam @@ -0,0 +1,9 @@ +App( + appid="notification_settings", + name="LCD and Notifications", + apptype=FlipperAppType.SETTINGS, + entry_point="notification_settings_app", + requires=["notification"], + stack_size=1 * 1024, + order=20, +) diff --git a/applications/notification/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c similarity index 99% rename from applications/notification/notification_settings_app.c rename to applications/settings/notification_settings/notification_settings_app.c index 894938f4..d462163a 100644 --- a/applications/notification/notification_settings_app.c +++ b/applications/settings/notification_settings/notification_settings_app.c @@ -1,5 +1,5 @@ #include -#include "notification_app.h" +#include #include #include #include diff --git a/applications/settings/power_settings_app/application.fam b/applications/settings/power_settings_app/application.fam new file mode 100644 index 00000000..a5b1966b --- /dev/null +++ b/applications/settings/power_settings_app/application.fam @@ -0,0 +1,13 @@ +App( + appid="power_settings", + name="Power", + apptype=FlipperAppType.SETTINGS, + entry_point="power_settings_app", + requires=[ + "gui", + "power", + ], + flags=["InsomniaSafe"], + stack_size=1 * 1024, + order=40, +) diff --git a/applications/power/power_settings_app/power_settings_app.c b/applications/settings/power_settings_app/power_settings_app.c similarity index 100% rename from applications/power/power_settings_app/power_settings_app.c rename to applications/settings/power_settings_app/power_settings_app.c diff --git a/applications/power/power_settings_app/power_settings_app.h b/applications/settings/power_settings_app/power_settings_app.h similarity index 100% rename from applications/power/power_settings_app/power_settings_app.h rename to applications/settings/power_settings_app/power_settings_app.h diff --git a/applications/power/power_settings_app/scenes/power_settings_scene.c b/applications/settings/power_settings_app/scenes/power_settings_scene.c similarity index 100% rename from applications/power/power_settings_app/scenes/power_settings_scene.c rename to applications/settings/power_settings_app/scenes/power_settings_scene.c diff --git a/applications/power/power_settings_app/scenes/power_settings_scene.h b/applications/settings/power_settings_app/scenes/power_settings_scene.h similarity index 100% rename from applications/power/power_settings_app/scenes/power_settings_scene.h rename to applications/settings/power_settings_app/scenes/power_settings_scene.h diff --git a/applications/power/power_settings_app/scenes/power_settings_scene_battery_info.c b/applications/settings/power_settings_app/scenes/power_settings_scene_battery_info.c similarity index 100% rename from applications/power/power_settings_app/scenes/power_settings_scene_battery_info.c rename to applications/settings/power_settings_app/scenes/power_settings_scene_battery_info.c diff --git a/applications/power/power_settings_app/scenes/power_settings_scene_config.h b/applications/settings/power_settings_app/scenes/power_settings_scene_config.h similarity index 100% rename from applications/power/power_settings_app/scenes/power_settings_scene_config.h rename to applications/settings/power_settings_app/scenes/power_settings_scene_config.h diff --git a/applications/power/power_settings_app/scenes/power_settings_scene_power_off.c b/applications/settings/power_settings_app/scenes/power_settings_scene_power_off.c similarity index 100% rename from applications/power/power_settings_app/scenes/power_settings_scene_power_off.c rename to applications/settings/power_settings_app/scenes/power_settings_scene_power_off.c diff --git a/applications/power/power_settings_app/scenes/power_settings_scene_reboot.c b/applications/settings/power_settings_app/scenes/power_settings_scene_reboot.c similarity index 100% rename from applications/power/power_settings_app/scenes/power_settings_scene_reboot.c rename to applications/settings/power_settings_app/scenes/power_settings_scene_reboot.c diff --git a/applications/power/power_settings_app/scenes/power_settings_scene_start.c b/applications/settings/power_settings_app/scenes/power_settings_scene_start.c similarity index 100% rename from applications/power/power_settings_app/scenes/power_settings_scene_start.c rename to applications/settings/power_settings_app/scenes/power_settings_scene_start.c diff --git a/applications/power/power_settings_app/views/battery_info.c b/applications/settings/power_settings_app/views/battery_info.c similarity index 100% rename from applications/power/power_settings_app/views/battery_info.c rename to applications/settings/power_settings_app/views/battery_info.c diff --git a/applications/power/power_settings_app/views/battery_info.h b/applications/settings/power_settings_app/views/battery_info.h similarity index 100% rename from applications/power/power_settings_app/views/battery_info.h rename to applications/settings/power_settings_app/views/battery_info.h diff --git a/applications/storage_settings/application.fam b/applications/settings/storage_settings/application.fam similarity index 100% rename from applications/storage_settings/application.fam rename to applications/settings/storage_settings/application.fam diff --git a/applications/storage_settings/scenes/storage_settings_scene.c b/applications/settings/storage_settings/scenes/storage_settings_scene.c similarity index 100% rename from applications/storage_settings/scenes/storage_settings_scene.c rename to applications/settings/storage_settings/scenes/storage_settings_scene.c diff --git a/applications/storage_settings/scenes/storage_settings_scene.h b/applications/settings/storage_settings/scenes/storage_settings_scene.h similarity index 100% rename from applications/storage_settings/scenes/storage_settings_scene.h rename to applications/settings/storage_settings/scenes/storage_settings_scene.h diff --git a/applications/storage_settings/scenes/storage_settings_scene_benchmark.c b/applications/settings/storage_settings/scenes/storage_settings_scene_benchmark.c similarity index 100% rename from applications/storage_settings/scenes/storage_settings_scene_benchmark.c rename to applications/settings/storage_settings/scenes/storage_settings_scene_benchmark.c diff --git a/applications/storage_settings/scenes/storage_settings_scene_config.h b/applications/settings/storage_settings/scenes/storage_settings_scene_config.h similarity index 100% rename from applications/storage_settings/scenes/storage_settings_scene_config.h rename to applications/settings/storage_settings/scenes/storage_settings_scene_config.h diff --git a/applications/storage_settings/scenes/storage_settings_scene_factory_reset.c b/applications/settings/storage_settings/scenes/storage_settings_scene_factory_reset.c similarity index 100% rename from applications/storage_settings/scenes/storage_settings_scene_factory_reset.c rename to applications/settings/storage_settings/scenes/storage_settings_scene_factory_reset.c diff --git a/applications/storage_settings/scenes/storage_settings_scene_format_confirm.c b/applications/settings/storage_settings/scenes/storage_settings_scene_format_confirm.c similarity index 100% rename from applications/storage_settings/scenes/storage_settings_scene_format_confirm.c rename to applications/settings/storage_settings/scenes/storage_settings_scene_format_confirm.c diff --git a/applications/storage_settings/scenes/storage_settings_scene_formatting.c b/applications/settings/storage_settings/scenes/storage_settings_scene_formatting.c similarity index 100% rename from applications/storage_settings/scenes/storage_settings_scene_formatting.c rename to applications/settings/storage_settings/scenes/storage_settings_scene_formatting.c diff --git a/applications/storage_settings/scenes/storage_settings_scene_internal_info.c b/applications/settings/storage_settings/scenes/storage_settings_scene_internal_info.c similarity index 100% rename from applications/storage_settings/scenes/storage_settings_scene_internal_info.c rename to applications/settings/storage_settings/scenes/storage_settings_scene_internal_info.c diff --git a/applications/storage_settings/scenes/storage_settings_scene_sd_info.c b/applications/settings/storage_settings/scenes/storage_settings_scene_sd_info.c similarity index 100% rename from applications/storage_settings/scenes/storage_settings_scene_sd_info.c rename to applications/settings/storage_settings/scenes/storage_settings_scene_sd_info.c diff --git a/applications/storage_settings/scenes/storage_settings_scene_start.c b/applications/settings/storage_settings/scenes/storage_settings_scene_start.c similarity index 100% rename from applications/storage_settings/scenes/storage_settings_scene_start.c rename to applications/settings/storage_settings/scenes/storage_settings_scene_start.c diff --git a/applications/storage_settings/scenes/storage_settings_scene_unmount_confirm.c b/applications/settings/storage_settings/scenes/storage_settings_scene_unmount_confirm.c similarity index 100% rename from applications/storage_settings/scenes/storage_settings_scene_unmount_confirm.c rename to applications/settings/storage_settings/scenes/storage_settings_scene_unmount_confirm.c diff --git a/applications/storage_settings/scenes/storage_settings_scene_unmounted.c b/applications/settings/storage_settings/scenes/storage_settings_scene_unmounted.c similarity index 100% rename from applications/storage_settings/scenes/storage_settings_scene_unmounted.c rename to applications/settings/storage_settings/scenes/storage_settings_scene_unmounted.c diff --git a/applications/storage_settings/storage_settings.c b/applications/settings/storage_settings/storage_settings.c similarity index 100% rename from applications/storage_settings/storage_settings.c rename to applications/settings/storage_settings/storage_settings.c diff --git a/applications/storage_settings/storage_settings.h b/applications/settings/storage_settings/storage_settings.h similarity index 100% rename from applications/storage_settings/storage_settings.h rename to applications/settings/storage_settings/storage_settings.h diff --git a/applications/settings/system/application.fam b/applications/settings/system/application.fam new file mode 100644 index 00000000..0fc456b2 --- /dev/null +++ b/applications/settings/system/application.fam @@ -0,0 +1,9 @@ +App( + appid="system_settings", + name="System", + apptype=FlipperAppType.SETTINGS, + entry_point="system_settings_app", + requires=["gui"], + stack_size=1 * 1024, + order=70, +) diff --git a/applications/system/system_settings.c b/applications/settings/system/system_settings.c similarity index 100% rename from applications/system/system_settings.c rename to applications/settings/system/system_settings.c diff --git a/applications/system/system_settings.h b/applications/settings/system/system_settings.h similarity index 100% rename from applications/system/system_settings.h rename to applications/settings/system/system_settings.h diff --git a/applications/system/application.fam b/applications/system/application.fam index 0fc456b2..a59f840e 100644 --- a/applications/system/application.fam +++ b/applications/system/application.fam @@ -1,9 +1,10 @@ App( - appid="system_settings", - name="System", - apptype=FlipperAppType.SETTINGS, - entry_point="system_settings_app", - requires=["gui"], - stack_size=1 * 1024, - order=70, + appid="system_apps", + name="Applications not shown in menus", + apptype=FlipperAppType.METAPACKAGE, + provides=[ + "updater_app", + "storage_move_to_sd", + # "archive", + ], ) diff --git a/applications/storage_move_to_sd/application.fam b/applications/system/storage_move_to_sd/application.fam similarity index 100% rename from applications/storage_move_to_sd/application.fam rename to applications/system/storage_move_to_sd/application.fam diff --git a/applications/storage_move_to_sd/scenes/storage_move_to_sd_scene.c b/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene.c similarity index 100% rename from applications/storage_move_to_sd/scenes/storage_move_to_sd_scene.c rename to applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene.c diff --git a/applications/storage_move_to_sd/scenes/storage_move_to_sd_scene.h b/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene.h similarity index 100% rename from applications/storage_move_to_sd/scenes/storage_move_to_sd_scene.h rename to applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene.h diff --git a/applications/storage_move_to_sd/scenes/storage_move_to_sd_scene_config.h b/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_config.h similarity index 100% rename from applications/storage_move_to_sd/scenes/storage_move_to_sd_scene_config.h rename to applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_config.h diff --git a/applications/storage_move_to_sd/scenes/storage_move_to_sd_scene_confirm.c b/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_confirm.c similarity index 100% rename from applications/storage_move_to_sd/scenes/storage_move_to_sd_scene_confirm.c rename to applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_confirm.c diff --git a/applications/storage_move_to_sd/scenes/storage_move_to_sd_scene_progress.c b/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_progress.c similarity index 100% rename from applications/storage_move_to_sd/scenes/storage_move_to_sd_scene_progress.c rename to applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_progress.c diff --git a/applications/storage_move_to_sd/storage_move_to_sd.c b/applications/system/storage_move_to_sd/storage_move_to_sd.c similarity index 100% rename from applications/storage_move_to_sd/storage_move_to_sd.c rename to applications/system/storage_move_to_sd/storage_move_to_sd.c diff --git a/applications/storage_move_to_sd/storage_move_to_sd.h b/applications/system/storage_move_to_sd/storage_move_to_sd.h similarity index 100% rename from applications/storage_move_to_sd/storage_move_to_sd.h rename to applications/system/storage_move_to_sd/storage_move_to_sd.h diff --git a/applications/updater/application.fam b/applications/system/updater/application.fam similarity index 100% rename from applications/updater/application.fam rename to applications/system/updater/application.fam diff --git a/applications/updater/cli/updater_cli.c b/applications/system/updater/cli/updater_cli.c similarity index 100% rename from applications/updater/cli/updater_cli.c rename to applications/system/updater/cli/updater_cli.c diff --git a/applications/updater/scenes/updater_scene.c b/applications/system/updater/scenes/updater_scene.c similarity index 100% rename from applications/updater/scenes/updater_scene.c rename to applications/system/updater/scenes/updater_scene.c diff --git a/applications/updater/scenes/updater_scene.h b/applications/system/updater/scenes/updater_scene.h similarity index 100% rename from applications/updater/scenes/updater_scene.h rename to applications/system/updater/scenes/updater_scene.h diff --git a/applications/updater/scenes/updater_scene_config.h b/applications/system/updater/scenes/updater_scene_config.h similarity index 100% rename from applications/updater/scenes/updater_scene_config.h rename to applications/system/updater/scenes/updater_scene_config.h diff --git a/applications/updater/scenes/updater_scene_error.c b/applications/system/updater/scenes/updater_scene_error.c similarity index 98% rename from applications/updater/scenes/updater_scene_error.c rename to applications/system/updater/scenes/updater_scene_error.c index 362c471a..21bf1637 100644 --- a/applications/updater/scenes/updater_scene_error.c +++ b/applications/system/updater/scenes/updater_scene_error.c @@ -1,4 +1,4 @@ -#include "updater/updater_i.h" +#include "../updater_i.h" #include "updater_scene.h" #include diff --git a/applications/updater/scenes/updater_scene_loadcfg.c b/applications/system/updater/scenes/updater_scene_loadcfg.c similarity index 99% rename from applications/updater/scenes/updater_scene_loadcfg.c rename to applications/system/updater/scenes/updater_scene_loadcfg.c index 1fd87d00..c7f48c78 100644 --- a/applications/updater/scenes/updater_scene_loadcfg.c +++ b/applications/system/updater/scenes/updater_scene_loadcfg.c @@ -1,4 +1,4 @@ -#include "updater/updater_i.h" +#include "../updater_i.h" #include "updater_scene.h" #include diff --git a/applications/updater/scenes/updater_scene_main.c b/applications/system/updater/scenes/updater_scene_main.c similarity index 98% rename from applications/updater/scenes/updater_scene_main.c rename to applications/system/updater/scenes/updater_scene_main.c index 5f7aeaca..2ef0732c 100644 --- a/applications/updater/scenes/updater_scene_main.c +++ b/applications/system/updater/scenes/updater_scene_main.c @@ -3,8 +3,8 @@ #include #include -#include "updater/updater_i.h" -#include "updater/views/updater_main.h" +#include "../updater_i.h" +#include "../views/updater_main.h" #include "updater_scene.h" static void sd_mount_callback(const void* message, void* context) { diff --git a/applications/updater/updater.c b/applications/system/updater/updater.c similarity index 100% rename from applications/updater/updater.c rename to applications/system/updater/updater.c diff --git a/applications/updater/updater_i.h b/applications/system/updater/updater_i.h similarity index 100% rename from applications/updater/updater_i.h rename to applications/system/updater/updater_i.h diff --git a/applications/updater/util/update_task.c b/applications/system/updater/util/update_task.c similarity index 100% rename from applications/updater/util/update_task.c rename to applications/system/updater/util/update_task.c diff --git a/applications/updater/util/update_task.h b/applications/system/updater/util/update_task.h similarity index 100% rename from applications/updater/util/update_task.h rename to applications/system/updater/util/update_task.h diff --git a/applications/updater/util/update_task_i.h b/applications/system/updater/util/update_task_i.h similarity index 100% rename from applications/updater/util/update_task_i.h rename to applications/system/updater/util/update_task_i.h diff --git a/applications/updater/util/update_task_worker_backup.c b/applications/system/updater/util/update_task_worker_backup.c similarity index 100% rename from applications/updater/util/update_task_worker_backup.c rename to applications/system/updater/util/update_task_worker_backup.c diff --git a/applications/updater/util/update_task_worker_flasher.c b/applications/system/updater/util/update_task_worker_flasher.c similarity index 100% rename from applications/updater/util/update_task_worker_flasher.c rename to applications/system/updater/util/update_task_worker_flasher.c diff --git a/applications/updater/views/updater_main.c b/applications/system/updater/views/updater_main.c similarity index 100% rename from applications/updater/views/updater_main.c rename to applications/system/updater/views/updater_main.c diff --git a/applications/updater/views/updater_main.h b/applications/system/updater/views/updater_main.h similarity index 100% rename from applications/updater/views/updater_main.h rename to applications/system/updater/views/updater_main.h diff --git a/applications_user/.gitignore b/applications_user/.gitignore new file mode 100644 index 00000000..72e8ffc0 --- /dev/null +++ b/applications_user/.gitignore @@ -0,0 +1 @@ +* diff --git a/applications_user/README.md b/applications_user/README.md new file mode 100644 index 00000000..8bb7823c --- /dev/null +++ b/applications_user/README.md @@ -0,0 +1 @@ +Put your custom applications in this folder. \ No newline at end of file diff --git a/assets/.gitignore b/assets/.gitignore index eb20456f..9bc0bdc0 100644 --- a/assets/.gitignore +++ b/assets/.gitignore @@ -1,2 +1,3 @@ -/headers /core2_firmware +/resources/Manifest +/resources/apps/* \ No newline at end of file diff --git a/assets/SConscript b/assets/SConscript index ecb10956..47713d1a 100644 --- a/assets/SConscript +++ b/assets/SConscript @@ -1,13 +1,5 @@ Import("env") -# HACHHACK -# Currently injected to CPPPATH by libs - since they are built earlier and depend on assets -# env.Append( -# CPPPATH=[ -# Dir("./compiled"), -# ] -# ) - assetsenv = env.Clone( tools=["fbt_assets"], FW_LIB_NAME="assets", @@ -27,7 +19,9 @@ if not assetsenv["VERBOSE"]: icons_src = assetsenv.GlobRecursive("*.png", "icons") icons_src += assetsenv.GlobRecursive("frame_rate", "icons") -icons = assetsenv.IconBuilder(Dir("compiled"), Dir("#/assets/icons")) +icons = assetsenv.IconBuilder( + assetsenv.Dir("compiled"), ICON_SRC_DIR=assetsenv.Dir("#/assets/icons") +) assetsenv.Depends(icons, icons_src) assetsenv.Alias("icons", icons) @@ -92,7 +86,6 @@ if assetsenv["IS_BASE_FIRMWARE"]: assetsenv.Alias("dolphin_ext", dolphin_external) # Resources manifest - resources = assetsenv.Command( "#/assets/resources/Manifest", assetsenv.GlobRecursive("*", "resources", exclude="Manifest"), @@ -101,11 +94,14 @@ if assetsenv["IS_BASE_FIRMWARE"]: "${RESMANIFESTCOMSTR}", ), ) - assetsenv.Precious(resources) - assetsenv.NoClean(resources) assetsenv.AlwaysBuild(resources) + assetsenv.Clean( + resources, + assetsenv.Dir("#/assets/resources/apps"), + ) # Exporting resources node to external environment + env["FW_ASSETS_HEADERS"] = assets_parts env["FW_RESOURCES"] = resources assetsenv.Alias("resources", resources) diff --git a/assets/icons/Common/Round_loader_8x8/frame_01.png b/assets/icons/Common/Round_loader_8x8/frame_01.png new file mode 100644 index 00000000..a5dc239d Binary files /dev/null and b/assets/icons/Common/Round_loader_8x8/frame_01.png differ diff --git a/assets/icons/Common/Round_loader_8x8/frame_02.png b/assets/icons/Common/Round_loader_8x8/frame_02.png new file mode 100644 index 00000000..162d8a8f Binary files /dev/null and b/assets/icons/Common/Round_loader_8x8/frame_02.png differ diff --git a/assets/icons/Common/Round_loader_8x8/frame_03.png b/assets/icons/Common/Round_loader_8x8/frame_03.png new file mode 100644 index 00000000..5483e473 Binary files /dev/null and b/assets/icons/Common/Round_loader_8x8/frame_03.png differ diff --git a/assets/icons/Common/Round_loader_8x8/frame_04.png b/assets/icons/Common/Round_loader_8x8/frame_04.png new file mode 100644 index 00000000..ce2fbbd4 Binary files /dev/null and b/assets/icons/Common/Round_loader_8x8/frame_04.png differ diff --git a/assets/icons/Common/Round_loader_8x8/frame_05.png b/assets/icons/Common/Round_loader_8x8/frame_05.png new file mode 100644 index 00000000..8b786c02 Binary files /dev/null and b/assets/icons/Common/Round_loader_8x8/frame_05.png differ diff --git a/assets/icons/Common/Round_loader_8x8/frame_rate b/assets/icons/Common/Round_loader_8x8/frame_rate new file mode 100644 index 00000000..d8263ee9 --- /dev/null +++ b/assets/icons/Common/Round_loader_8x8/frame_rate @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/assets/icons/NFC/Keychain.png b/assets/icons/Infrared/CoolHi_25x27.png similarity index 84% rename from assets/icons/NFC/Keychain.png rename to assets/icons/Infrared/CoolHi_25x27.png index 7ba1b11d..cea29a5b 100644 Binary files a/assets/icons/NFC/Keychain.png and b/assets/icons/Infrared/CoolHi_25x27.png differ diff --git a/assets/icons/Infrared/CoolHi_hvr_25x27.png b/assets/icons/Infrared/CoolHi_hvr_25x27.png new file mode 100644 index 00000000..692ac7b8 Binary files /dev/null and b/assets/icons/Infrared/CoolHi_hvr_25x27.png differ diff --git a/assets/icons/Infrared/CoolLo_25x27.png b/assets/icons/Infrared/CoolLo_25x27.png new file mode 100644 index 00000000..23288e44 Binary files /dev/null and b/assets/icons/Infrared/CoolLo_25x27.png differ diff --git a/assets/icons/Infrared/CoolLo_hvr_25x27.png b/assets/icons/Infrared/CoolLo_hvr_25x27.png new file mode 100644 index 00000000..ae5316e4 Binary files /dev/null and b/assets/icons/Infrared/CoolLo_hvr_25x27.png differ diff --git a/assets/icons/Infrared/Dehumidify_25x27.png b/assets/icons/Infrared/Dehumidify_25x27.png new file mode 100644 index 00000000..dca77ae4 Binary files /dev/null and b/assets/icons/Infrared/Dehumidify_25x27.png differ diff --git a/assets/icons/Infrared/Dehumidify_hvr_25x27.png b/assets/icons/Infrared/Dehumidify_hvr_25x27.png new file mode 100644 index 00000000..2c593ca8 Binary files /dev/null and b/assets/icons/Infrared/Dehumidify_hvr_25x27.png differ diff --git a/assets/icons/Infrared/HeatHi_25x27.png b/assets/icons/Infrared/HeatHi_25x27.png new file mode 100644 index 00000000..a1724f99 Binary files /dev/null and b/assets/icons/Infrared/HeatHi_25x27.png differ diff --git a/assets/icons/Infrared/HeatHi_hvr_25x27.png b/assets/icons/Infrared/HeatHi_hvr_25x27.png new file mode 100644 index 00000000..b92108d6 Binary files /dev/null and b/assets/icons/Infrared/HeatHi_hvr_25x27.png differ diff --git a/assets/icons/Infrared/HeatLo_25x27.png b/assets/icons/Infrared/HeatLo_25x27.png new file mode 100644 index 00000000..af2e59d4 Binary files /dev/null and b/assets/icons/Infrared/HeatLo_25x27.png differ diff --git a/assets/icons/Infrared/HeatLo_hvr_25x27.png b/assets/icons/Infrared/HeatLo_hvr_25x27.png new file mode 100644 index 00000000..6708edb3 Binary files /dev/null and b/assets/icons/Infrared/HeatLo_hvr_25x27.png differ diff --git a/assets/icons/Infrared/Off_25x27.png b/assets/icons/Infrared/Off_25x27.png new file mode 100644 index 00000000..c1510060 Binary files /dev/null and b/assets/icons/Infrared/Off_25x27.png differ diff --git a/assets/icons/Infrared/Off_hvr_25x27.png b/assets/icons/Infrared/Off_hvr_25x27.png new file mode 100644 index 00000000..d5e5e6f4 Binary files /dev/null and b/assets/icons/Infrared/Off_hvr_25x27.png differ diff --git a/assets/icons/NFC/Keychain_39x36.png b/assets/icons/NFC/Keychain_39x36.png new file mode 100644 index 00000000..d15850b5 Binary files /dev/null and b/assets/icons/NFC/Keychain_39x36.png differ diff --git a/assets/icons/NFC/NFC_manual.png b/assets/icons/NFC/NFC_manual_60x50.png similarity index 100% rename from assets/icons/NFC/NFC_manual.png rename to assets/icons/NFC/NFC_manual_60x50.png diff --git a/assets/icons/NFC/Reader_detect_43x40.png b/assets/icons/NFC/Reader_detect_43x40.png new file mode 100644 index 00000000..d833a527 Binary files /dev/null and b/assets/icons/NFC/Reader_detect_43x40.png differ diff --git a/assets/icons/NFC/Restoring.png b/assets/icons/NFC/Restoring_38x32.png similarity index 100% rename from assets/icons/NFC/Restoring.png rename to assets/icons/NFC/Restoring_38x32.png diff --git a/assets/icons/PIN/Pin_arrow_up7x9.png b/assets/icons/PIN/Pin_arrow_up_7x9.png similarity index 100% rename from assets/icons/PIN/Pin_arrow_up7x9.png rename to assets/icons/PIN/Pin_arrow_up_7x9.png diff --git a/assets/icons/StatusBar/GameMode_11x8.png b/assets/icons/StatusBar/GameMode_11x8.png new file mode 100644 index 00000000..49f2e25b Binary files /dev/null and b/assets/icons/StatusBar/GameMode_11x8.png differ diff --git a/assets/resources/Manifest b/assets/resources/Manifest deleted file mode 100644 index 8bfdcef7..00000000 --- a/assets/resources/Manifest +++ /dev/null @@ -1,241 +0,0 @@ -V:0 -T:1660218073 -D:badusb -D:dolphin -D:infrared -D:music_player -D:nfc -D:subghz -D:u2f -F:0e41ba26498b7511d7c9e6e6b5e3b149:1592:badusb/demo_macos.txt -F:46a332993ca94b9aa692030ebaa19c70:1552:badusb/demo_windows.txt -D:dolphin/L1_Boxing_128x64 -D:dolphin/L1_Cry_128x64 -D:dolphin/L1_Furippa1_128x64 -D:dolphin/L1_Laptop_128x51 -D:dolphin/L1_Leaving_sad_128x64 -D:dolphin/L1_Mad_fist_128x64 -D:dolphin/L1_Read_books_128x64 -D:dolphin/L1_Recording_128x51 -D:dolphin/L1_Sleep_128x64 -D:dolphin/L1_Waves_128x50 -D:dolphin/L2_Furippa2_128x64 -D:dolphin/L2_Hacking_pc_128x64 -D:dolphin/L2_Soldering_128x64 -D:dolphin/L3_Furippa3_128x64 -D:dolphin/L3_Hijack_radio_128x64 -D:dolphin/L3_Lab_research_128x54 -F:d1148ab5354eaf4fa7f959589d840932:1563:dolphin/manifest.txt -F:d37be8444102ec5cde5fe3a85d55b57d:481:dolphin/L1_Boxing_128x64/frame_0.bm -F:54fb07443bc153ded9589b74d23b4263:461:dolphin/L1_Boxing_128x64/frame_1.bm -F:e007afe130d699c715b99ce8e5b407bd:531:dolphin/L1_Boxing_128x64/frame_2.bm -F:a999a9a6c76c66158f1aa5ccb56de7c9:437:dolphin/L1_Boxing_128x64/frame_3.bm -F:ec6af9cb451ab16c0fa62e95e8134b49:459:dolphin/L1_Boxing_128x64/frame_4.bm -F:2aa0c1e7bf1131b9dc172aa595ec01f2:450:dolphin/L1_Boxing_128x64/frame_5.bm -F:bbc8f750d17d156438c5cfe1122ec7f4:442:dolphin/L1_Boxing_128x64/frame_6.bm -F:f6e51ada3e3285e330714dab5b4277dd:418:dolphin/L1_Boxing_128x64/meta.txt -F:ab33a6f37209541f3db938d1cfe1706f:889:dolphin/L1_Cry_128x64/frame_0.bm -F:1b3fdeb404af0f7402caa5a5e091a8f8:911:dolphin/L1_Cry_128x64/frame_1.bm -F:4db644b173af72f3d371d2bd81f76b05:910:dolphin/L1_Cry_128x64/frame_2.bm -F:cd4c0ef67a8e514edecd9600242db068:923:dolphin/L1_Cry_128x64/frame_3.bm -F:ee02e9589e0714d3e2bc0d93aa294ccb:894:dolphin/L1_Cry_128x64/frame_4.bm -F:7703a7d9745d13b45d73ce4b86b4cdc8:940:dolphin/L1_Cry_128x64/frame_5.bm -F:ee6de6a0ed903317c4948cb445e0a9a8:915:dolphin/L1_Cry_128x64/frame_6.bm -F:a3892e45826c66f48d3d64fb81521446:934:dolphin/L1_Cry_128x64/frame_7.bm -F:680b12cc4dad722d6583b7e710bfc297:516:dolphin/L1_Cry_128x64/meta.txt -F:4911eaa7cb84ced19e5dea2af51b91a5:294:dolphin/L1_Furippa1_128x64/frame_0.bm -F:5669bee57c7b3d93a1665dd87fd5372a:325:dolphin/L1_Furippa1_128x64/frame_1.bm -F:80b48a77682b853e6236cd1c89083e6f:465:dolphin/L1_Furippa1_128x64/frame_10.bm -F:9d8ea10bf3d3831cb4a94957dc0b41c6:698:dolphin/L1_Furippa1_128x64/frame_11.bm -F:2dbb3125ea63550906fba8f7ec7b1da3:541:dolphin/L1_Furippa1_128x64/frame_12.bm -F:6a06b718957dca9caa63a4f3baa73abb:584:dolphin/L1_Furippa1_128x64/frame_13.bm -F:5450bf16c3d2fceaf5e6ea585b7ef7c1:610:dolphin/L1_Furippa1_128x64/frame_14.bm -F:535c0eca62703eb7df36f17334a6191b:719:dolphin/L1_Furippa1_128x64/frame_15.bm -F:7c03af85ade9b791755f3a4d106c2b7c:458:dolphin/L1_Furippa1_128x64/frame_16.bm -F:41b8fea16ad8705f4594e6119eade395:400:dolphin/L1_Furippa1_128x64/frame_17.bm -F:2db7fd3da5208a8e41902ae27cf41702:333:dolphin/L1_Furippa1_128x64/frame_18.bm -F:7e47428442e0f04959fc6afde979936e:351:dolphin/L1_Furippa1_128x64/frame_2.bm -F:0eb187078f169d7a852e97ecf430aea0:324:dolphin/L1_Furippa1_128x64/frame_3.bm -F:967c402971a442a5bf28eba804bb3ff4:387:dolphin/L1_Furippa1_128x64/frame_4.bm -F:175cb930fba0fc86f54a3a109b741708:390:dolphin/L1_Furippa1_128x64/frame_5.bm -F:f8c3ee1ab657549d1d00c1c72d8d2ff5:407:dolphin/L1_Furippa1_128x64/frame_6.bm -F:4911eaa7cb84ced19e5dea2af51b91a5:294:dolphin/L1_Furippa1_128x64/frame_7.bm -F:8f649ff34b224f4e564644a4494c54ed:283:dolphin/L1_Furippa1_128x64/frame_8.bm -F:3ec3c40d26bf8d3e691b1335d20d4ec0:312:dolphin/L1_Furippa1_128x64/frame_9.bm -F:ebe088426d184cf6651288accd21add6:241:dolphin/L1_Furippa1_128x64/meta.txt -F:d02fdfd1a3b89da00d2acf32bd09da80:555:dolphin/L1_Laptop_128x51/frame_0.bm -F:7e29ea503d41023fa3895d15458f106d:557:dolphin/L1_Laptop_128x51/frame_1.bm -F:eb55e0629de873f537d8412ced528eb4:560:dolphin/L1_Laptop_128x51/frame_2.bm -F:1516472ab3c140dd5bd4d089caa44747:556:dolphin/L1_Laptop_128x51/frame_3.bm -F:61172f89cf0a17bd7f978edccdeed166:560:dolphin/L1_Laptop_128x51/frame_4.bm -F:9d54913928c7e9477b6b8a43f3767621:554:dolphin/L1_Laptop_128x51/frame_5.bm -F:5243d6272bbb213e9c17af07ee011402:553:dolphin/L1_Laptop_128x51/frame_6.bm -F:aa68e0f28f117891ba0f4d7613224fc6:560:dolphin/L1_Laptop_128x51/frame_7.bm -F:9ef1935ab29fe70bbc517f4b602547d7:403:dolphin/L1_Laptop_128x51/meta.txt -F:6ce34e62c5bf4764a4163101afe63e60:514:dolphin/L1_Leaving_sad_128x64/frame_0.bm -F:19a0e0c518d222d91d24b8712ab6bb80:526:dolphin/L1_Leaving_sad_128x64/frame_1.bm -F:837bfb424c8d8a3bfbda7d6a28ba5a5c:316:dolphin/L1_Leaving_sad_128x64/frame_10.bm -F:1a69b6f63a96e0958837ea8b21db3966:294:dolphin/L1_Leaving_sad_128x64/frame_11.bm -F:c3ea827593a4563d544dfb7e99d73885:322:dolphin/L1_Leaving_sad_128x64/frame_12.bm -F:1e3842669191fe9599f830ac133e0751:542:dolphin/L1_Leaving_sad_128x64/frame_2.bm -F:9161660e6827bd776a15eefa2a8add19:557:dolphin/L1_Leaving_sad_128x64/frame_3.bm -F:d01a79fdb4f84397d82bf9927aeb71e0:488:dolphin/L1_Leaving_sad_128x64/frame_4.bm -F:316e30ef319c080fab2a79c21e526319:469:dolphin/L1_Leaving_sad_128x64/frame_5.bm -F:09a812d59b60b5fe7724057daa14ad60:499:dolphin/L1_Leaving_sad_128x64/frame_6.bm -F:9eb07b76cc864a0ce2918d68e41d4500:486:dolphin/L1_Leaving_sad_128x64/frame_7.bm -F:cf8c4cc4abbd700b096037b7ebfd0e31:403:dolphin/L1_Leaving_sad_128x64/frame_8.bm -F:889728ded689203aa82193e573912d18:317:dolphin/L1_Leaving_sad_128x64/frame_9.bm -F:2bff1f09ad1e9059a60e08990ca1d414:477:dolphin/L1_Leaving_sad_128x64/meta.txt -F:c31a882e95ed5c69fd63226db2188710:520:dolphin/L1_Mad_fist_128x64/frame_0.bm -F:740326828f6ba6e29373943ba835e77f:540:dolphin/L1_Mad_fist_128x64/frame_1.bm -F:0c9693dda040fd73ca6d773a10924bd8:542:dolphin/L1_Mad_fist_128x64/frame_10.bm -F:425c1d101debd1e9502db2628640b704:505:dolphin/L1_Mad_fist_128x64/frame_11.bm -F:aa576f7dbd14ec682f6c50314165fb14:501:dolphin/L1_Mad_fist_128x64/frame_12.bm -F:712335eabefb8c7bb7fb2f4301419c10:500:dolphin/L1_Mad_fist_128x64/frame_13.bm -F:b6e11711ea4dcc2e64f267d888f91baf:515:dolphin/L1_Mad_fist_128x64/frame_2.bm -F:61bdd22a2b1e67efe093b6acf7dfadce:538:dolphin/L1_Mad_fist_128x64/frame_3.bm -F:20ae06a3ce7a07656e578edb024e2b3f:512:dolphin/L1_Mad_fist_128x64/frame_4.bm -F:45cf2bd55365a7328df39fe98a496cc9:519:dolphin/L1_Mad_fist_128x64/frame_5.bm -F:4b8840eebb3a4a1ead69a7130816047e:524:dolphin/L1_Mad_fist_128x64/frame_6.bm -F:0de4497a5fbf80cc93e523465c5e3122:515:dolphin/L1_Mad_fist_128x64/frame_7.bm -F:32d8ddeb19bfa415fe283666b1e323a2:517:dolphin/L1_Mad_fist_128x64/frame_8.bm -F:a42a0578c2d0411500fb3485a3beb536:526:dolphin/L1_Mad_fist_128x64/frame_9.bm -F:10a521c78168a5928c859494e2a61cd2:349:dolphin/L1_Mad_fist_128x64/meta.txt -F:61565b7be9a69a60ce2dbae0273df347:653:dolphin/L1_Read_books_128x64/frame_0.bm -F:cf5a2d423540e3af37e789d70c9c1fbf:653:dolphin/L1_Read_books_128x64/frame_1.bm -F:c91935861979d024e6637b8810889878:650:dolphin/L1_Read_books_128x64/frame_2.bm -F:0c007a30f396f3e7a0ded2b24080357d:646:dolphin/L1_Read_books_128x64/frame_3.bm -F:323a52816dd79d6d3186f451e26e06ad:650:dolphin/L1_Read_books_128x64/frame_4.bm -F:494f27958f4cea9b94d09cf27725c5cd:652:dolphin/L1_Read_books_128x64/frame_5.bm -F:a6a7491fe80255e1745c9f293da52805:646:dolphin/L1_Read_books_128x64/frame_6.bm -F:238497e6643fd491cd6002e98c615c05:647:dolphin/L1_Read_books_128x64/frame_7.bm -F:300651e8f53d9a29ae38d4b9292c73cf:643:dolphin/L1_Read_books_128x64/frame_8.bm -F:3d9568deeff646b677092902a98f9ceb:325:dolphin/L1_Read_books_128x64/meta.txt -F:2aba555567ab70cff003ded4138c6721:663:dolphin/L1_Recording_128x51/frame_0.bm -F:8456c6e86825957e5662e2f08eb6c116:657:dolphin/L1_Recording_128x51/frame_1.bm -F:2e4a1aca5afa5a6ab254884210875eb4:629:dolphin/L1_Recording_128x51/frame_10.bm -F:9f1cf96598e3d935879b1d0c97705778:659:dolphin/L1_Recording_128x51/frame_11.bm -F:409abfeca974e5649affcd1faafea988:628:dolphin/L1_Recording_128x51/frame_2.bm -F:66b2a5abf05acbf79f9943e01b8b8cec:654:dolphin/L1_Recording_128x51/frame_3.bm -F:d55c5ed28c2ff48f42ab30b420d64fa3:662:dolphin/L1_Recording_128x51/frame_4.bm -F:2ce12d8cfdd953c9dadb9459c580a320:622:dolphin/L1_Recording_128x51/frame_5.bm -F:da631e3837fcdf3ee9e6abdf17fb764b:664:dolphin/L1_Recording_128x51/frame_6.bm -F:604a7cdac2491c9bc2e88b9e91c99dcc:626:dolphin/L1_Recording_128x51/frame_7.bm -F:fc94649dc98244dd9a0ab7fe62721d3c:663:dolphin/L1_Recording_128x51/frame_8.bm -F:b2475ab8ee26cbd9a403ee603520bd35:661:dolphin/L1_Recording_128x51/frame_9.bm -F:a7c2b3b420706712149cc2426c68df4f:219:dolphin/L1_Recording_128x51/meta.txt -F:9858fd34b55cebcb9be50c5710212a13:580:dolphin/L1_Sleep_128x64/frame_0.bm -F:e47ef8c846083b8fde028b1724861444:589:dolphin/L1_Sleep_128x64/frame_1.bm -F:9749bd05b47fd07cc3a41ab201f86bf4:582:dolphin/L1_Sleep_128x64/frame_2.bm -F:edf11266b20b846ace622e41cd36906b:597:dolphin/L1_Sleep_128x64/frame_3.bm -F:8fbb96a9d809d85fa6bad931fe4e6fe2:510:dolphin/L1_Sleep_128x64/meta.txt -F:283b41f1b2c581c510ff176293b7288a:443:dolphin/L1_Waves_128x50/frame_0.bm -F:c9fc5127e1d8a4217b6b177716725ba0:448:dolphin/L1_Waves_128x50/frame_1.bm -F:8e0797bf26d5d8d3cbeb99798c222b80:463:dolphin/L1_Waves_128x50/frame_2.bm -F:da02b1deb3119b31f2b8f182d5bf3242:472:dolphin/L1_Waves_128x50/frame_3.bm -F:8e6fb4133acbda7e5bb9adad0aed306c:620:dolphin/L1_Waves_128x50/meta.txt -F:be80d2fa903e3250b69c063a1eef0621:350:dolphin/L2_Furippa2_128x64/frame_0.bm -F:9e628f5e154f12d6c57b13befed1f5f6:385:dolphin/L2_Furippa2_128x64/frame_1.bm -F:80b48a77682b853e6236cd1c89083e6f:465:dolphin/L2_Furippa2_128x64/frame_10.bm -F:9d8ea10bf3d3831cb4a94957dc0b41c6:698:dolphin/L2_Furippa2_128x64/frame_11.bm -F:2dbb3125ea63550906fba8f7ec7b1da3:541:dolphin/L2_Furippa2_128x64/frame_12.bm -F:6a06b718957dca9caa63a4f3baa73abb:584:dolphin/L2_Furippa2_128x64/frame_13.bm -F:5450bf16c3d2fceaf5e6ea585b7ef7c1:610:dolphin/L2_Furippa2_128x64/frame_14.bm -F:e3c92103f403857b502081d3b058e53a:740:dolphin/L2_Furippa2_128x64/frame_15.bm -F:432669d796bbf7be1d14f5b7db036a92:533:dolphin/L2_Furippa2_128x64/frame_16.bm -F:53485c6b465c80a1ce8ddf03c4976039:451:dolphin/L2_Furippa2_128x64/frame_17.bm -F:333b75b16c088428a28259c931630fb9:397:dolphin/L2_Furippa2_128x64/frame_18.bm -F:ed02d68380382361f3f01cbf01d13b0c:402:dolphin/L2_Furippa2_128x64/frame_2.bm -F:b0ba042d7b60dc5681182b1d4005f0a2:374:dolphin/L2_Furippa2_128x64/frame_3.bm -F:518a84fa5a4e9e7f84246d5d82e87f15:440:dolphin/L2_Furippa2_128x64/frame_4.bm -F:9b7b0ae6f4f55d30cb43b0465216aa25:449:dolphin/L2_Furippa2_128x64/frame_5.bm -F:03b153949b0dae2efe1fc5f0dc57a0ef:466:dolphin/L2_Furippa2_128x64/frame_6.bm -F:be80d2fa903e3250b69c063a1eef0621:350:dolphin/L2_Furippa2_128x64/frame_7.bm -F:a8433f451cf3efc4ce2fb04a38c1f84f:319:dolphin/L2_Furippa2_128x64/frame_8.bm -F:d32a11bf9779d57191c1e59fe69cf83d:317:dolphin/L2_Furippa2_128x64/frame_9.bm -F:ebe088426d184cf6651288accd21add6:241:dolphin/L2_Furippa2_128x64/meta.txt -F:af4ec0085c29732085c51b18dc97bc27:543:dolphin/L2_Hacking_pc_128x64/frame_0.bm -F:eb141965fb6fb9f8b28766bac92abe1a:545:dolphin/L2_Hacking_pc_128x64/frame_1.bm -F:f7b33d3541dab08aaf4e8375e262b982:548:dolphin/L2_Hacking_pc_128x64/frame_2.bm -F:03634d90c54fd235aa76c0f9f794c80b:608:dolphin/L2_Hacking_pc_128x64/frame_3.bm -F:4c77406302f3fb74f8bdba568097082a:609:dolphin/L2_Hacking_pc_128x64/frame_4.bm -F:b0d1783358094534ac95b3455124d5fe:409:dolphin/L2_Hacking_pc_128x64/meta.txt -F:584c92e6fb15e99389b84d567e6d4d02:699:dolphin/L2_Soldering_128x64/frame_0.bm -F:3fa01b93460379204b6d14f43573b4f3:688:dolphin/L2_Soldering_128x64/frame_1.bm -F:6fad29757d4b7231b1d0ec53d0529b45:699:dolphin/L2_Soldering_128x64/frame_10.bm -F:e82c83e5a03abf4f6a1efd0a0f1ca33a:689:dolphin/L2_Soldering_128x64/frame_2.bm -F:7f9f310e22ef85af225dd1aefa2c47ba:689:dolphin/L2_Soldering_128x64/frame_3.bm -F:1ff31af6f90f07c0cdfa3283f52a5adc:693:dolphin/L2_Soldering_128x64/frame_4.bm -F:1a8f25aff949860cc6ffc79b4f48d5dd:696:dolphin/L2_Soldering_128x64/frame_5.bm -F:dbaa75feb8aebaf9b1cc5201c29952b8:712:dolphin/L2_Soldering_128x64/frame_6.bm -F:ee356bd981fba90c402d8e08d3015792:732:dolphin/L2_Soldering_128x64/frame_7.bm -F:09d5c5a685df606562d407bb9dac798e:705:dolphin/L2_Soldering_128x64/frame_8.bm -F:5451816e73bad029b3b9f3f55d294582:698:dolphin/L2_Soldering_128x64/frame_9.bm -F:c38ffad11987faf5ba6e363ead705e78:319:dolphin/L2_Soldering_128x64/meta.txt -F:2e083023ab65d1f99bba71f9aae6db9a:398:dolphin/L3_Furippa3_128x64/frame_0.bm -F:8cf20e07d84fd6a1157ba932beca70ea:438:dolphin/L3_Furippa3_128x64/frame_1.bm -F:018344c951691b7b1d77c1c6729d3e42:559:dolphin/L3_Furippa3_128x64/frame_10.bm -F:07008e2508064ab7a8467802472a9803:728:dolphin/L3_Furippa3_128x64/frame_11.bm -F:2dbb3125ea63550906fba8f7ec7b1da3:541:dolphin/L3_Furippa3_128x64/frame_12.bm -F:6a06b718957dca9caa63a4f3baa73abb:584:dolphin/L3_Furippa3_128x64/frame_13.bm -F:5450bf16c3d2fceaf5e6ea585b7ef7c1:610:dolphin/L3_Furippa3_128x64/frame_14.bm -F:e333224a4bed87b606df57a252ed4887:741:dolphin/L3_Furippa3_128x64/frame_15.bm -F:a20a6abfbd66fc3f92c66adacc4444a3:559:dolphin/L3_Furippa3_128x64/frame_16.bm -F:c1e051dce6b90e4f69b4792d0356a6b3:492:dolphin/L3_Furippa3_128x64/frame_17.bm -F:377f3621507c6590120cbc1c8ca92999:445:dolphin/L3_Furippa3_128x64/frame_18.bm -F:81f09c0fcd2bddb8a107a199e7149230:463:dolphin/L3_Furippa3_128x64/frame_2.bm -F:ed7fd1ada1070493462c1899f7372baf:424:dolphin/L3_Furippa3_128x64/frame_3.bm -F:e5fb2cdc4e08d6abff3191d37a1007ed:499:dolphin/L3_Furippa3_128x64/frame_4.bm -F:923a05250e5a93c7db7bbbf48448d164:504:dolphin/L3_Furippa3_128x64/frame_5.bm -F:1e9628db28a9a908c4a4b24cb16c5d20:521:dolphin/L3_Furippa3_128x64/frame_6.bm -F:2e083023ab65d1f99bba71f9aae6db9a:398:dolphin/L3_Furippa3_128x64/frame_7.bm -F:f1ec6e12daba9490f9e2e0e308ae3f83:419:dolphin/L3_Furippa3_128x64/frame_8.bm -F:106997120ad4cd23bd51e6f26bd7d74d:435:dolphin/L3_Furippa3_128x64/frame_9.bm -F:ebe088426d184cf6651288accd21add6:241:dolphin/L3_Furippa3_128x64/meta.txt -F:42970030123b2468984785fea7c60318:524:dolphin/L3_Hijack_radio_128x64/frame_0.bm -F:491c6d8ef21e48ca0f6b5fbd269c820b:527:dolphin/L3_Hijack_radio_128x64/frame_1.bm -F:ff499c8716c5f7fc1110a5ee82bda20c:550:dolphin/L3_Hijack_radio_128x64/frame_10.bm -F:ee39d82d6efc6a6992d19b6d75a6c509:572:dolphin/L3_Hijack_radio_128x64/frame_11.bm -F:5d14e8cb9d67bf8f597d6c749d07a135:539:dolphin/L3_Hijack_radio_128x64/frame_12.bm -F:9461004b75a34a36097668159c4cabe6:579:dolphin/L3_Hijack_radio_128x64/frame_13.bm -F:c925d4b1dff9c81463944cf930d7da8d:526:dolphin/L3_Hijack_radio_128x64/frame_2.bm -F:f98ed80cfab3a94b580be81654401c89:529:dolphin/L3_Hijack_radio_128x64/frame_3.bm -F:97ba548c27732be9e05fb8f7be8204ce:571:dolphin/L3_Hijack_radio_128x64/frame_4.bm -F:524932eb2391057fc1dea7237c7086e3:574:dolphin/L3_Hijack_radio_128x64/frame_5.bm -F:8eb9672f719926ac9c4c158575f388cd:524:dolphin/L3_Hijack_radio_128x64/frame_6.bm -F:7ca93fbab93bc278d4a11089d624a07b:655:dolphin/L3_Hijack_radio_128x64/frame_7.bm -F:37b4368f0b7235f3a7347bf499541666:645:dolphin/L3_Hijack_radio_128x64/frame_8.bm -F:ea9c3d7bab4756c2916369d5e130fa71:611:dolphin/L3_Hijack_radio_128x64/frame_9.bm -F:8583743f18a12ff647d3478e7aebdad6:230:dolphin/L3_Hijack_radio_128x64/meta.txt -F:f5f02a9df03bba734bdb7ed3297795f0:611:dolphin/L3_Lab_research_128x54/frame_0.bm -F:8f9655ad286464159443922d00e45620:614:dolphin/L3_Lab_research_128x54/frame_1.bm -F:7793b1bc107d4ea2e311e92dc16bf946:576:dolphin/L3_Lab_research_128x54/frame_10.bm -F:f24b8409f9dc770f3845424fe0ab489e:585:dolphin/L3_Lab_research_128x54/frame_11.bm -F:4ea93c4482dac43f40b67cc308f21e6d:571:dolphin/L3_Lab_research_128x54/frame_12.bm -F:cf3bb68dc78c568db22f37057a9fdd66:615:dolphin/L3_Lab_research_128x54/frame_13.bm -F:79719219aaebc95ea525def9173cabf5:618:dolphin/L3_Lab_research_128x54/frame_2.bm -F:05572cfd756704acd6ce9d6c15d03fc0:608:dolphin/L3_Lab_research_128x54/frame_3.bm -F:a26604a0d5427d5cf62a7a911a68b16c:615:dolphin/L3_Lab_research_128x54/frame_4.bm -F:9edc345fe53017970f93dc680818e63e:618:dolphin/L3_Lab_research_128x54/frame_5.bm -F:cf3bb68dc78c568db22f37057a9fdd66:615:dolphin/L3_Lab_research_128x54/frame_6.bm -F:5442895c85f769349288aa3df0990f9d:585:dolphin/L3_Lab_research_128x54/frame_7.bm -F:33b8fde22f34ef556b64b77164bc19b0:578:dolphin/L3_Lab_research_128x54/frame_8.bm -F:f267f0654781049ca323b11bb4375519:581:dolphin/L3_Lab_research_128x54/frame_9.bm -F:41106c0cbc5144f151b2b2d3daaa0527:727:dolphin/L3_Lab_research_128x54/meta.txt -D:infrared/assets -F:a565c3a381695a5f2ba7a0698460238c:74833:infrared/assets/tv.ir -F:a157a80f5a668700403d870c23b9567d:470:music_player/Marble_Machine.fmf -D:nfc/assets -F:81dc04c7b181f94b644079a71476dff4:4742:nfc/assets/aid.nfc -F:86efbebdf41bb6bf15cc51ef88f069d5:2565:nfc/assets/country_code.nfc -F:41b4f08774249014cb8d3dffa5f5c07d:1757:nfc/assets/currency_code.nfc -F:c60e862919731b0bd538a1001bbc1098:17453:nfc/assets/mf_classic_dict.nfc -D:subghz/assets -F:dda1ef895b8a25fde57c874feaaef997:650:subghz/assets/came_atomo -F:788eef2cc74e29f3388463d6607dab0d:3264:subghz/assets/keeloq_mfcodes -F:9214f9c10463b746a27e82ce0b96e040:465:subghz/assets/keeloq_mfcodes_user -F:653bd8d349055a41e1152e557d4a52d3:202:subghz/assets/nice_flor_s -F:c1c63fbd5f5aa3ea504027014652191f:1150:subghz/assets/setting_user -D:u2f/assets -F:7e11e688e39034bbb9d88410044795e1:365:u2f/assets/cert.der -F:f60b88c20ed479ed9684e249f7134618:264:u2f/assets/cert_key.u2f diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir new file mode 100644 index 00000000..b1075b2f --- /dev/null +++ b/assets/resources/infrared/assets/ac.ir @@ -0,0 +1,38 @@ +Filetype: IR library file +Version: 1 +# +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 502 3436 510 475 509 476 508 477 507 477 507 479 505 480 504 480 504 490 504 481 502 482 501 483 563 420 511 474 510 475 509 476 508 485 561 423 508 476 508 477 507 478 506 479 505 480 504 481 503 517 508 476 508 478 506 479 505 479 505 481 503 483 521 1456 501 498 507 479 505 480 504 481 503 482 501 483 563 421 562 422 509 499 506 479 505 480 504 481 503 482 502 484 510 1451 506 479 505 1542 562 1396 509 471 502 476 508 469 504 3425 511 +# +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 507 3430 506 479 505 480 504 481 503 481 503 483 501 485 509 1453 504 1465 503 482 502 483 511 473 500 485 509 476 508 477 507 478 506 487 507 477 507 478 506 479 505 480 504 482 502 483 501 484 500 523 503 482 502 484 500 485 509 476 508 476 508 478 506 1456 501 501 504 482 502 483 501 484 500 485 509 476 508 477 507 1455 502 509 506 479 505 1457 500 485 509 476 508 1454 503 482 502 483 501 568 499 1459 509 1450 507 471 502 474 510 3421 505 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 504 3433 503 482 502 484 510 474 510 475 509 476 508 478 506 1456 564 1405 510 475 509 476 508 502 482 477 507 478 506 479 505 480 504 489 505 480 504 481 503 482 502 483 511 473 511 474 510 475 509 509 506 479 505 480 504 481 503 482 512 473 511 474 510 476 508 1469 509 475 509 476 508 477 507 478 506 479 505 480 504 481 503 505 510 475 509 502 482 503 481 504 480 505 478 507 477 1459 509 560 507 1451 506 473 511 493 480 1450 507 3422 503 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 525 3615 530 506 561 474 562 474 562 473 563 473 531 505 562 1502 528 1542 562 474 562 474 530 505 531 504 532 504 532 504 616 419 533 510 589 447 526 509 527 509 527 509 527 508 528 508 528 507 529 542 525 510 526 509 527 509 527 509 527 508 528 508 528 1535 527 524 533 503 533 503 533 502 534 502 534 502 534 501 535 501 525 534 533 502 534 502 534 501 535 502 534 1529 533 503 533 503 533 587 533 497 528 501 524 1536 526 501 524 3609 526 +# +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 531 3406 530 455 529 456 528 457 537 447 537 448 535 450 534 1429 528 1442 536 448 536 449 534 451 532 452 532 453 530 454 530 455 529 464 530 454 529 456 528 457 537 448 536 449 535 450 533 451 533 490 535 449 534 450 534 451 533 452 532 453 531 455 529 1433 534 1443 535 449 535 450 534 452 531 453 530 454 530 455 529 456 538 472 532 452 532 454 530 1433 535 1427 530 1432 536 1427 530 1431 537 1511 530 448 536 1422 535 1423 534 1422 535 3395 530 +# +name: Heat_lo +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 506 3430 506 478 506 479 505 480 504 481 503 482 502 484 500 1463 505 1465 503 482 502 483 501 484 500 485 509 476 508 477 507 478 506 486 508 477 507 478 506 479 505 480 504 481 503 482 502 483 500 523 502 482 502 483 501 484 500 485 509 476 508 478 506 1455 502 498 507 478 506 479 505 481 503 482 501 483 500 484 500 485 509 500 505 481 502 482 502 1461 507 1455 502 1459 509 476 508 477 507 563 504 1453 504 1454 503 1454 503 1453 504 3426 499 diff --git a/assets/unit_tests/subghz/oregon2_raw.sub b/assets/unit_tests/subghz/oregon2_raw.sub new file mode 100644 index 00000000..549a60db --- /dev/null +++ b/assets/unit_tests/subghz/oregon2_raw.sub @@ -0,0 +1,20 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok270Async +Protocol: RAW +RAW_Data: 889 -130 325 -64 457 -560 165 -68 199 -170 67 -66 265 -132 133 -666 67 -166 431 -66 201 -98 297 -100 595 -66 199 -134 65 -100 795 -132 99 -168 501 -200 331 -132 265 -102 265 -134 423 -98 521 -226 65 -166 431 -134 99 -100 133 -464 195 -326 623 -100 673 -98 321 -200 65 -136 369 -166 65 -68 97 -166 165 -334 265 -102 231 -166 101 -170 65 -170 265 -136 931 -100 133 -134 563 -66 333 -100 427 -66 163 -390 231 -66 193 -130 461 -166 557 -100 99 -198 263 -100 197 -294 231 -232 299 -134 199 -170 267 -134 631 -98 235 -100 499 -68 463 -100 65 -134 335 -170 273 -134 297 -100 67 -66 197 -166 67 -134 301 -168 537 -470 99 -134 433 -132 199 -192 261 -100 523 -164 459 -132 259 -332 359 -64 227 -96 131 -132 687 -132 363 -136 329 -434 99 -334 133 -100 401 -132 233 -700 233 -170 337 -66 371 -68 233 -202 531 -266 731 -66 465 -100 167 -100 133 -232 335 -166 239 -102 367 -232 231 -100 167 -134 201 -136 301 -168 199 -300 231 -98 237 -134 233 -102 329 -132 261 -134 199 -66 265 -136 99 -170 167 -134 199 -166 167 -136 367 -298 197 -200 99 -166 469 -136 439 -66 303 -134 295 -100 433 -134 899 -266 363 -132 197 -160 555 -324 129 -96 97 -128 257 -132 97 -394 257 -98 195 -166 459 -332 395 -132 633 -134 301 -100 131 -332 169 -168 395 -166 263 -540 783 -100 287 -130 295 -96 225 -296 133 -98 99 -100 461 -164 545 -130 99 -66 301 -68 265 -100 235 -134 235 -70 333 -102 497 -66 233 -364 301 -170 103 -66 165 -336 733 -200 133 -100 263 -102 65 -136 465 -200 1035 -198 165 -170 67 -302 631 -100 429 -332 65 -128 129 -130 159 -128 159 -66 161 -96 325 -164 261 -100 197 -162 65 -96 99 -130 65 -102 333 -100 199 -98 389 -330 129 -128 229 -66 425 -366 229 -64 261 -100 227 -96 227 -526 301 -200 97 -66 699 -334 67 -100 399 -198 787 -98 297 -134 429 -100 3245 -64 527 -98 131 -526 633 -68 133 -302 1459 -164 971 -102 237 -136 1439 -266 1131 -66 599 -200 303 -332 325 -130 389 -166 371 -66 333 -102 65 -100 233 -234 327 -266 233 -166 297 -100 225 -130 163 -336 99 -596 199 -330 131 -66 331 -338 263 -358 197 -168 877 -66 227 -96 63 -130 263 -162 225 -290 197 -198 357 -132 297 -262 165 -456 227 -98 399 -296 95 -132 99 -98 457 -200 199 -168 535 -100 567 -134 327 -130 193 -130 683 -102 101 -132 233 -170 943 -166 827 -66 267 -102 503 -68 1325 -164 +RAW_Data: 1607 -68 233 -166 1167 -70 531 -134 335 -168 131 -66 299 -402 899 -66 461 -66 457 -98 953 -98 165 -66 293 -230 881 -64 393 -166 589 -66 289 -66 1093 -204 333 -98 2745 -132 2019 -170 925 -68 269 -102 1469 -136 2301 -68 1355 -100 527 -66 975 -68 1445 -98 2397 -100 1733 -66 703 -100 995 -100 135 -136 235 -202 167 -134 2071 -166 339 -170 201 -268 129 -66 465 -66 365 -100 197 -164 129 -98 161 -96 423 -66 675 -66 1543 -136 567 -200 767 -202 65 -100 1401 -66 623 -136 567 -234 67 -236 197 -194 97 -66 263 -66 1827 -392 1893 -98 165 -268 133 -132 231 -162 225 -98 695 -198 563 -100 301 -332 267 -102 341 -66 99 -132 1299 -130 525 -68 161 -96 357 -98 353 -100 131 -100 131 -98 163 -132 323 -100 535 -66 1323 -130 133 -66 235 -134 1497 -132 387 -98 129 -162 2623 -134 163 -68 167 -66 959 -232 495 -68 131 -134 867 -134 865 -66 333 -98 305 -134 231 -98 765 -198 397 -432 165 -66 165 -366 265 -102 541 -100 261 -162 331 -134 457 -66 491 -196 97 -266 193 -262 65 -166 231 -266 497 -360 263 -98 587 -164 259 -98 231 -66 359 -100 267 -102 271 -168 97 -262 63 -66 261 -130 227 -130 295 -164 65 -66 265 -200 597 -134 267 -170 603 -100 97 -466 231 -264 97 -168 99 -66 65 -200 199 -100 267 -404 303 -102 201 -204 235 -134 131 -198 335 -298 327 -130 291 -164 63 -162 295 -262 197 -130 95 -130 195 -96 159 -130 161 -66 231 -100 165 -66 199 -134 363 -66 267 -168 165 -168 167 -100 165 -530 363 -432 99 -232 65 -132 395 -328 229 -98 197 -132 161 -96 191 -292 197 -204 133 -100 399 -166 531 -332 235 -168 99 -66 325 -158 553 -132 129 -226 231 -134 99 -462 129 -64 289 -100 193 -66 355 -164 291 -198 131 -298 197 -198 373 -268 335 -234 427 -68 199 -132 267 -232 131 -66 783 -326 63 -162 161 -130 227 -66 259 -562 233 -464 303 -102 201 -334 301 -134 297 -198 229 -66 127 -166 99 -100 197 -198 571 -66 457 -134 361 -424 131 -328 163 -98 63 -100 505 -102 201 -1094 229 -164 65 -230 789 -236 2505 -166 201 -170 163 -64 1139 -66 927 -100 295 -198 723 -100 365 -66 459 -196 3033 -272 199 -66 499 -202 1319 -232 295 -298 131 -362 97 -164 129 -132 65 -98 197 -130 129 -98 261 -130 97 -98 229 -96 425 -66 227 -166 483 -66 163 -326 567 -68 235 -68 67 -66 167 -66 235 -330 425 -164 63 -66 427 -102 167 -66 669 -132 429 -200 65 -102 133 -100 197 -368 +RAW_Data: 65 -134 2481 -228 65 -130 229 -228 763 -136 603 -166 1619 -98 1763 -102 837 -166 321 -66 951 -130 2067 -66 259 -132 1835 -66 437 -102 701 -66 565 -68 363 -70 1113 -66 1989 -164 257 -128 351 -162 1055 -232 265 -170 309 -200 435 -166 833 -102 2467 -132 595 -66 773 -166 1615 -98 131 -96 485 -64 517 -166 197 -68 1231 -68 403 -100 263 -134 233 -100 503 -100 333 -266 729 -66 199 -100 369 -68 1239 -100 197 -68 299 -170 337 -100 825 -132 163 -66 4205 -64 161 -100 635 -66 907 -66 1017 -166 1709 -100 201 -266 657 -68 463 -166 331 -164 293 -64 259 -162 129 -262 597 -134 701 -136 67 -168 235 -136 303 -170 1417 -66 263 -98 857 -100 659 -166 97 -100 2497 -64 2495 -98 719 -128 227 -130 2217 -164 623 -264 719 -134 329 -98 1371 -100 553 -294 165 -66 1163 -100 329 -196 649 -200 1123 -68 263 -100 593 -266 333 -102 1133 -136 131 -132 603 -200 1819 -66 489 -66 563 -266 1113 -230 165 -66 423 -68 335 -100 101 -100 1073 -132 897 -100 101 -100 499 -134 173 -138 763 -238 371 -130 403 -166 203 -102 271 -136 269 -166 99 -168 263 -96 425 -66 331 -234 133 -400 231 -132 453 -66 459 -164 199 -68 237 -132 163 -198 161 -196 265 -132 65 -64 195 -130 357 -164 663 -68 167 -600 131 -98 133 -304 203 -134 433 -98 261 -130 199 -100 237 -100 229 -326 99 -98 331 -132 99 -294 165 -66 303 -134 99 -232 133 -136 99 -68 267 -198 233 -138 67 -166 367 -100 333 -168 267 -200 369 -266 135 -404 1939 -132 231 -160 161 -64 293 -98 331 -132 339 -104 135 -100 197 -430 263 -202 233 -64 195 -162 129 -64 227 -298 265 -68 697 -66 301 -68 231 -300 131 -368 769 -234 265 -98 195 -324 97 -752 229 -126 355 -98 257 -98 287 -64 427 -132 295 -262 197 -170 369 -102 267 -100 169 -68 201 -102 2551 -136 635 -134 639 -134 99 -132 197 -200 371 -66 731 -132 199 -138 733 -304 433 -68 729 -440 197 -68 99 -102 165 -266 261 -164 491 -296 489 -194 257 -164 133 -134 237 -68 335 -98 227 -130 229 -98 295 -98 231 -202 267 -236 233 -136 331 -130 195 -128 261 -430 261 -162 97 -224 99 -130 193 -96 197 -162 229 -396 97 -98 227 -364 267 -100 99 -100 233 -236 697 -164 227 -196 63 -98 327 -230 325 -66 129 -196 95 -98 195 -130 325 -430 131 -194 129 -454 161 -196 235 -68 433 -134 667 -164 355 -236 101 -98 2143 -134 1827 -198 63 -198 65 -64 2859 -64 619 -66 97 -130 3157 -66 679 -194 1491 -98 +RAW_Data: 951 -64 393 -100 955 -132 4715 -100 131 -66 199 -204 1541 -66 929 -130 1347 -166 665 -132 233 -132 67 -102 433 -100 595 -228 997 -66 505 -68 133 -98 231 -68 571 -134 1371 -232 231 -270 135 -102 97 -66 867 -100 269 -68 967 -100 1649 -66 65 -66 951 -68 65 -202 363 -200 779 -102 1449 -294 419 -130 361 -230 1079 -164 163 -260 893 -102 333 -100 533 -166 467 -100 135 -66 135 -202 369 -100 199 -100 269 -134 301 -166 229 -66 101 -134 199 -134 1293 -64 779 -62 831 -66 1243 -68 267 -102 197 -100 395 -98 455 -64 621 -132 877 -98 199 -100 2101 -134 503 -100 2035 -134 735 -236 475 -136 237 -132 133 -134 1229 -100 133 -66 167 -68 2655 -100 1807 -100 1095 -264 825 -98 163 -66 491 -98 161 -128 953 -100 773 -100 131 -66 67 -134 457 -130 63 -64 389 -98 715 -66 425 -300 97 -100 1515 -66 303 -68 99 -98 721 -64 887 -132 65 -132 165 -66 635 -68 2801 -66 1561 -100 751 -98 129 -64 725 -136 201 -100 333 -204 573 -104 1745 -134 99 -66 129 -64 595 -134 167 -102 337 -134 567 -134 1131 -138 1207 -100 269 -68 135 -100 1143 -134 2139 -68 1701 -162 991 -596 431 -66 99 -132 657 -66 391 -320 357 -260 259 -98 429 -66 163 -228 65 -130 227 -66 261 -166 99 -98 131 -366 199 -134 463 -102 201 -98 231 -102 639 -238 301 -568 169 -610 265 -102 841 -198 297 -100 335 -132 263 -266 265 -68 469 -134 267 -68 933 -298 333 -298 729 -168 135 -136 437 -132 1137 -134 199 -68 265 -132 463 -166 129 -130 227 -98 297 -98 65 -132 97 -202 199 -232 305 -66 165 -198 365 -66 99 -98 299 -170 65 -136 301 -232 99 -564 133 -132 233 -170 99 -102 131 -134 65 -204 101 -98 297 -98 167 -762 233 -298 99 -326 395 -66 299 -132 369 -504 333 -98 483 -200 457 -164 63 -164 329 -162 65 -622 231 -268 131 -132 133 -134 131 -134 131 -66 99 -100 231 -66 167 -336 165 -98 197 -100 97 -264 321 -98 521 -132 163 -130 129 -294 297 -134 101 -102 265 -168 497 -68 197 -68 499 -134 269 -398 267 -130 203 -302 65 -498 271 -136 465 -292 131 -294 163 -198 329 -96 129 -98 193 -130 391 -330 165 -134 167 -170 297 -102 133 -136 135 -366 199 -132 423 -132 395 -168 65 -166 401 -98 229 -98 329 -98 99 -130 129 -228 261 -160 127 -426 389 -162 193 -132 131 -100 231 -168 67 -304 201 -68 765 -132 161 -162 193 -64 195 -64 295 -130 787 -98 419 -528 429 -66 363 -134 131 -100 133 -200 331 -98 +RAW_Data: 431 -66 1167 -68 937 -68 1003 -66 99 -132 941 -134 65 -66 365 -274 165 -236 367 -96 557 -134 675 -66 261 -164 127 -96 391 -164 161 -98 391 -292 163 -98 519 -196 165 -98 523 -66 195 -160 3343 -66 661 -100 2589 -136 307 -100 629 -136 639 -100 133 -168 405 -100 267 -66 465 -132 1171 -64 749 -64 165 -98 983 -100 163 -202 537 -66 327 -100 669 -100 401 -236 2885 -164 439 -134 97 -426 1931 -66 1385 -98 715 -98 519 -66 289 -162 97 -360 297 -166 163 -66 289 -66 555 -334 167 -230 429 -102 267 -132 943 -136 401 -68 929 -130 193 -68 467 -198 335 -66 963 -100 597 -132 197 -260 523 -232 1115 -102 1935 -66 1395 -134 305 -100 99 -66 199 -66 1071 -66 2357 -66 367 -498 769 -234 163 -130 191 -64 1211 -200 133 -102 201 -100 561 -366 361 -98 195 -100 537 -64 165 -196 1041 -332 133 -102 441 -230 4217 -66 1033 -66 167 -66 933 -100 565 -66 331 -164 673 -104 441 -66 533 -66 2095 -164 525 -66 297 -170 965 -198 421 -100 663 -832 65 -100 331 -164 231 -166 135 -168 237 -466 761 -134 891 -196 791 -198 257 -160 161 -98 293 -66 1081 -98 229 -130 327 -66 1301 -200 331 -166 101 -66 461 -100 2619 -132 1663 -98 1609 -134 499 -332 165 -370 67 -264 97 -96 259 -98 701 -402 197 -128 527 -236 233 -102 167 -134 303 -134 99 -166 299 -132 165 -200 467 -68 305 -168 207 -102 465 -102 729 -136 101 -374 327 -96 259 -98 467 -202 65 -66 673 -98 335 -404 135 -66 339 -204 99 -366 233 -68 365 -166 133 -102 867 -198 163 -162 163 -294 463 -332 165 -68 269 -268 331 -100 131 -166 299 -132 231 -400 263 -164 131 -266 267 -264 367 -66 371 -134 229 -104 267 -232 67 -466 265 -100 101 -100 165 -200 65 -200 301 -66 199 -168 233 -98 267 -66 67 -134 261 -196 261 -234 427 -294 65 -194 193 -66 259 -132 849 -96 63 -198 167 -294 95 -98 361 -164 261 -196 131 -132 437 -100 597 -262 327 -162 295 -98 295 -164 259 -196 425 -230 321 -66 195 -66 261 -496 99 -200 529 -132 133 -966 133 -132 165 -66 63 -128 491 -402 65 -262 299 -66 299 -202 265 -100 99 -668 97 -134 65 -100 101 -66 65 -266 691 -66 431 -166 167 -134 199 -370 899 -134 99 -100 1093 -166 163 -166 399 -98 327 -100 99 -168 135 -200 133 -202 429 -98 65 -98 197 -556 65 -66 97 -326 331 -166 333 -200 135 -100 235 -234 265 -98 65 -68 135 -66 335 -66 133 -298 99 -66 233 -164 435 -232 97 -132 97 -392 +RAW_Data: 99 -198 819 -66 1235 -98 321 -132 1091 -66 1307 -98 3059 -164 3305 -64 227 -98 591 -98 129 -66 229 -98 2143 -98 939 -68 563 -100 361 -232 945 -164 257 -96 229 -230 387 -64 195 -130 981 -294 587 -162 193 -98 1337 -66 293 -98 2665 -66 297 -98 647 -66 459 -132 491 -164 489 -96 595 -66 899 -66 837 -64 1151 -196 259 -98 357 -164 891 -132 1359 -134 197 -98 97 -98 261 -64 229 -96 461 -136 693 -100 201 -98 865 -66 599 -100 517 -132 709 -66 293 -298 655 -66 197 -130 129 -66 197 -98 4291 -66 673 -66 667 -132 1473 -132 133 -104 99 -66 163 -168 333 -134 1743 -132 1097 -132 99 -68 167 -602 1323 -352 99 -166 753 -98 423 -98 97 -66 1317 -228 1309 -98 1849 -66 1939 -132 601 -100 665 -100 1875 -66 695 -132 425 -66 425 -66 263 -134 165 -134 99 -98 829 -66 601 -166 131 -102 565 -66 301 -100 1099 -100 601 -138 533 -66 667 -234 561 -66 99 -68 2741 -98 199 -100 531 -168 101 -434 1027 -68 431 -66 403 -132 99 -98 565 -132 135 -100 399 -166 271 -236 233 -166 197 -366 99 -66 99 -168 503 -66 199 -170 207 -100 673 -368 99 -66 263 -168 133 -98 397 -268 337 -66 131 -132 231 -132 501 -134 99 -168 567 -138 103 -136 267 -298 231 -134 197 -160 321 -332 231 -98 131 -164 257 -64 163 -328 395 -66 331 -202 65 -168 133 -68 167 -100 233 -102 335 -66 197 -326 1101 -132 589 -100 811 -132 399 -136 269 -102 497 -66 559 -100 129 -98 855 -68 637 -102 65 -200 875 -68 233 -166 167 -66 529 -202 235 -102 231 -66 1237 -66 733 -98 1723 -132 101 -100 297 -66 829 -232 197 -100 367 -134 169 -166 167 -434 633 -100 235 -200 131 -134 233 -100 131 -100 331 -134 495 -432 65 -528 161 -130 295 -132 337 -136 133 -166 165 -100 269 -240 201 -336 133 -166 165 -238 199 -202 431 -434 99 -134 501 -166 231 -96 559 -202 167 -66 717 -98 987 -198 65 -64 163 -64 227 -98 555 -164 199 -64 361 -66 163 -98 129 -162 97 -130 161 -460 197 -230 681 -98 197 -98 329 -100 267 -266 291 -264 65 -100 329 -100 459 -200 363 -98 165 -134 231 -134 301 -134 231 -302 99 -132 101 -134 267 -136 233 -68 393 -422 163 -166 361 -166 99 -134 365 -134 133 -336 401 -66 495 -132 401 -168 133 -402 501 -136 1093 -862 165 -132 293 -300 289 -66 131 -164 391 -134 99 -360 359 -130 323 -200 423 -98 195 -162 295 -132 161 -98 129 -782 131 -426 227 -64 259 -166 63 -160 323 -98 261 -230 +RAW_Data: 231 -66 921 -66 355 -64 1019 -98 227 -258 163 -66 597 -232 1313 -132 163 -404 467 -236 901 -164 483 -98 195 -96 489 -134 103 -238 169 -66 67 -68 299 -100 497 -68 65 -134 1635 -304 1153 -100 539 -168 265 -200 499 -166 535 -100 397 -168 931 -100 131 -66 631 -134 897 -270 1233 -100 65 -132 131 -334 663 -66 163 -66 131 -132 705 -98 571 -200 433 -100 237 -234 229 -132 1627 -66 569 -100 715 -66 1863 -272 265 -68 301 -98 465 -68 97 -134 99 -66 395 -136 1405 -66 529 -132 63 -196 579 -132 413 -260 129 -136 101 -166 1201 -134 833 -134 393 -66 335 -172 201 -68 1027 -96 753 -64 815 -66 97 -64 1341 -132 289 -160 127 -66 99 -228 1083 -96 163 -66 259 -64 159 -98 2409 -168 767 -200 367 -66 1675 -66 1067 -98 3407 -200 99 -66 1403 -166 99 -134 439 -200 329 -136 599 -66 637 -66 835 -66 1099 -98 99 -66 463 -166 165 -100 461 -164 3037 -66 655 -66 97 -98 229 -130 355 -132 1443 -66 527 -98 881 -98 229 -162 127 -96 583 -64 65 -162 489 -166 885 -194 257 -98 1539 -66 293 -166 229 -132 655 -98 757 -49522 271 -758 689 -1264 737 -670 293 -1152 811 -1144 341 -664 773 -678 327 -1118 807 -1144 835 -1146 781 -1126 873 -1096 347 -622 877 -624 321 -1106 843 -1098 871 -1098 843 -1106 379 -610 841 -584 381 -1122 365 -602 845 -1116 837 -610 381 -1056 889 -1078 383 -614 827 -1110 877 -592 353 -1108 845 -1120 839 -1120 347 -602 849 -1110 865 -612 361 -1072 869 -1114 351 -618 861 -618 343 -1090 853 -1106 387 -618 797 -674 347 -1084 389 -574 867 -584 381 -1114 841 -1102 845 -1116 839 -1112 843 -1098 875 -1086 383 -584 865 -588 375 -1100 861 -1112 851 -1084 853 -1108 847 -1106 381 -584 857 -610 383 -1080 357 -602 871 -602 385 -1084 383 -616 823 -610 373 -1086 381 -590 871 -1084 839 -628 353 -1102 875 -1100 349 -9404 875 -1060 871 -1086 887 -1088 879 -1058 863 -1086 855 -1132 845 -1078 871 -1076 857 -1098 881 -1082 861 -1088 843 -1120 853 -1074 879 -1074 879 -1068 889 -614 341 -1090 387 -616 863 -624 345 -1088 391 -590 857 -612 385 -1058 393 -596 843 -1088 889 -1078 879 -578 387 -1082 875 -1076 415 -550 881 -1070 877 -592 391 -1114 821 -1104 373 -620 821 -624 361 -1072 903 -1086 855 -1092 843 -1086 905 -1054 387 -614 863 -618 347 -1088 853 -1114 845 -1090 867 -1070 381 -610 885 -584 385 -1052 407 -578 877 -1052 899 -600 389 -1048 907 -1074 383 -586 877 -1072 877 -594 359 -1076 875 -1082 891 -1088 363 -616 855 -1084 857 -592 381 -1088 883 -1086 385 -572 +RAW_Data: 889 -624 353 -1082 853 -1096 379 -594 853 -624 353 -1092 417 -582 847 -612 385 -1076 847 -1080 883 -1052 913 -1044 907 -1076 849 -1088 383 -602 867 -616 361 -1068 901 -1072 865 -1104 831 -1080 879 -1098 397 -586 855 -626 355 -1084 381 -592 873 -616 351 -1084 385 -624 821 -620 359 -1086 387 -584 883 -1086 877 -592 355 -1106 853 -1086 387 -69570 97 -100 99 -2620 131 -636 333 -102 235 -236 67 -68 363 -66 201 -100 567 -102 267 -164 101 -134 65 -68 197 -68 297 -166 671 -100 469 -336 165 -100 201 -66 169 -230 169 -204 329 -624 67 -98 265 -232 193 -168 299 -100 235 -138 101 -370 165 -294 333 -622 231 -130 129 -130 353 -132 195 -162 359 -164 67 -68 333 -100 133 -688 235 -236 497 -198 293 -98 129 -296 293 -164 229 -128 229 -132 193 -400 165 -66 163 -98 361 -164 355 -196 587 -164 131 -98 263 -554 99 -130 129 -130 191 -464 99 -132 67 -100 167 -604 329 -66 199 -68 133 -102 163 -66 2971 -132 785 -66 329 -96 323 -100 201 -136 301 -66 1959 -166 867 -134 467 -66 297 -100 835 -100 753 -166 165 -64 67 -370 335 -66 559 -232 165 -334 65 -162 129 -354 163 -64 131 -134 265 -300 263 -132 267 -296 327 -198 99 -132 535 -132 469 -866 231 -860 99 -232 503 -134 99 -198 233 -134 267 -200 97 -358 297 -164 259 -98 227 -166 135 -66 323 -100 97 -294 131 -164 129 -98 295 -96 129 -426 299 -100 67 -102 623 -100 163 -194 127 -360 563 -134 199 -428 493 -98 229 -130 257 -64 165 -100 131 -98 163 -692 357 -64 161 -98 321 -64 389 -230 65 -692 227 -130 261 -132 231 -162 287 -298 97 -460 393 -130 301 -168 331 -100 269 -202 101 -134 201 -102 99 -132 199 -204 235 -664 65 -562 133 -328 463 -100 291 -194 159 -162 227 -98 293 -328 165 -128 227 -574 535 -332 197 -168 65 -300 131 -66 389 -1078 131 -64 259 -64 223 -98 257 -164 63 -328 433 -134 65 -602 131 -68 333 -136 369 -66 297 -264 427 -66 97 -130 429 -102 133 -136 203 -240 167 -236 329 -526 67 -132 133 -168 331 -360 65 -66 331 -296 267 -134 469 -132 595 -230 661 -662 299 -100 265 -200 203 -168 801 -100 133 -68 399 -132 99 -100 161 -390 65 -298 65 -98 261 -130 161 -128 257 -66 67 -134 621 -98 227 -328 99 -230 129 -294 193 -96 195 -318 425 -526 129 -196 163 -162 65 -132 293 -130 63 -66 325 -128 63 -130 293 -66 199 -200 269 -206 133 -198 325 -98 163 -100 97 -98 261 -164 67 -98 167 -430 131 -494 131 -164 +RAW_Data: 97 -98 861 -66 1199 -166 231 -100 651 -166 197 -104 439 -98 131 -64 493 -98 883 -96 99 -98 3327 -66 131 -264 733 -134 2133 -166 131 -102 303 -136 535 -134 701 -98 355 -228 131 -202 99 -134 99 -100 791 -166 169 -202 671 -100 741 -100 263 -66 165 -68 935 -132 197 -198 673 -100 605 -66 1457 -98 1195 -166 2347 -134 505 -100 1469 -66 391 -100 229 -100 1171 -98 939 -100 459 -170 369 -134 231 -162 127 -98 95 -66 195 -98 195 -66 299 -100 331 -98 65 -232 369 -132 201 -68 167 -166 1481 -102 501 -160 1257 -66 2307 -64 623 -164 2079 -66 1101 -98 423 -64 659 -68 431 -136 99 -100 435 -130 167 -168 835 -200 135 -104 133 -100 503 -68 1437 -232 821 -132 357 -96 463 -66 263 -64 683 -132 165 -96 655 -166 3939 -100 1169 -132 2443 -98 197 -132 425 -234 233 -162 1043 -66 197 -100 2793 -134 167 -104 675 -100 197 -134 1367 -102 763 -132 265 -230 133 -102 365 -100 167 -66 1069 -66 837 -100 295 -160 97 -64 129 -132 617 -164 197 -100 133 -136 337 -172 133 -66 557 -98 951 -66 263 -130 587 -66 729 -196 335 -166 933 -432 369 -100 199 -296 225 -98 355 -66 129 -64 557 -98 289 -66 355 -128 193 -162 267 -134 299 -98 165 -170 303 -640 1031 -134 99 -66 135 -68 771 -166 171 -104 201 -134 131 -68 635 -428 661 -292 749 -430 1161 -100 905 -98 65 -98 657 -262 2837 -132 67 -66 265 -132 631 -66 1037 -296 97 -98 1703 -302 367 -100 505 -232 497 -362 333 -134 591 -100 755 -232 67 -130 587 -66 231 -168 65 -332 99 -66 267 -232 393 -134 65 -132 131 -428 133 -200 165 -202 199 -168 165 -102 269 -100 333 -852 201 -134 233 -202 65 -200 563 -768 265 -136 169 -102 169 -598 333 -202 267 -134 267 -328 163 -130 625 -500 199 -200 99 -270 65 -134 65 -198 65 -100 99 -596 493 -66 99 -66 331 -232 103 -136 373 -168 831 -170 65 -672 163 -102 133 -136 331 -100 333 -234 101 -100 99 -200 99 -100 201 -302 199 -600 301 -202 135 -134 705 -166 435 -530 97 -198 131 -198 195 -66 163 -392 293 -66 295 -370 229 -198 65 -100 405 -134 165 -134 133 -170 337 -236 205 -274 267 -134 329 -132 195 -132 503 -132 133 -136 133 -334 197 -196 299 -168 101 -100 233 -100 439 -134 301 -332 331 -298 433 -406 433 -68 167 -100 203 -100 101 -102 99 -328 397 -234 205 -168 133 -364 63 -202 397 -198 95 -394 267 -134 569 -66 201 -102 133 -136 101 -102 99 -132 99 -196 197 -498 197 -102 135 -170 +RAW_Data: 331 -164 63 -162 1267 -66 163 -130 129 -66 725 -164 231 -64 853 -66 101 -134 199 -102 99 -68 365 -66 357 -130 815 -64 357 -98 97 -98 97 -66 65 -466 231 -172 3749 -66 849 -130 917 -64 327 -64 1013 -98 555 -332 795 -100 571 -132 769 -132 401 -134 1297 -134 377 -138 435 -100 401 -100 667 -100 1761 -66 667 -66 1533 -236 233 -98 885 -130 457 -66 999 -66 165 -66 833 -134 695 -166 501 -66 499 -200 329 -64 197 -134 441 -100 2099 -98 491 -134 197 -130 2225 -132 65 -100 689 -64 193 -160 159 -96 195 -98 323 -164 259 -98 535 -472 771 -66 665 -270 665 -66 595 -266 2191 -64 643 -98 1287 -98 741 -100 233 -200 569 -194 261 -68 637 -100 97 -66 491 -158 395 -138 1017 -66 627 -262 559 -64 327 -98 263 -134 99 -102 201 -102 337 -66 167 -68 679 -100 471 -134 195 -66 133 -202 693 -96 197 -98 391 -164 99 -98 3883 -194 461 -100 237 -168 1891 -68 301 -68 969 -166 1439 -294 551 -130 389 -98 99 -196 167 -102 505 -66 569 -234 901 -98 407 -136 469 -66 769 -98 769 -166 1263 -266 297 -98 1701 -200 203 -168 329 -232 65 -100 329 -164 803 -100 135 -200 233 -166 135 -272 265 -134 197 -100 133 -134 539 -232 197 -396 165 -366 263 -68 233 -102 365 -132 233 -100 135 -266 199 -234 167 -232 97 -524 127 -128 389 -98 305 -364 261 -130 257 -162 589 -464 361 -66 229 -134 161 -100 203 -432 265 -66 199 -66 199 -366 229 -236 99 -134 99 -100 131 -168 133 -100 131 -236 267 -132 297 -264 291 -132 167 -234 65 -100 199 -66 333 -730 237 -440 365 -102 99 -100 99 -132 99 -100 1429 -134 427 -100 97 -100 131 -164 799 -170 1077 -100 431 -66 133 -168 737 -134 197 -230 65 -102 803 -132 491 -98 429 -198 471 -134 365 -66 299 -236 65 -66 2837 -102 399 -64 585 -64 523 -196 97 -98 295 -196 555 -160 261 -500 299 -396 333 -236 133 -68 327 -100 199 -204 699 -66 701 -100 65 -164 65 -370 195 -196 97 -66 193 -130 129 -360 195 -130 231 -96 291 -64 455 -228 293 -196 291 -162 97 -194 621 -130 847 -66 395 -66 161 -128 193 -130 293 -98 231 -170 67 -134 297 -360 167 -266 263 -526 263 -132 229 -98 191 -160 159 -100 721 -234 101 -100 99 -130 259 -258 265 -632 687 -164 133 -134 631 -100 199 -102 165 -560 299 -200 265 -332 431 -870 99 -266 503 -364 135 -66 269 -68 499 -100 265 -102 263 -102 569 -234 719 -132 99 -196 419 -262 163 -688 95 -66 165 -128 95 -66 +RAW_Data: 295 -98 987 -196 517 -100 489 -66 355 -132 563 -198 867 -134 1413 -134 541 -134 767 -100 193 -98 1799 -102 467 -134 299 -96 323 -66 261 -100 259 -66 229 -96 851 -66 369 -266 469 -66 101 -98 163 -136 267 -432 859 -130 523 -66 197 -134 1027 -132 227 -194 393 -98 807 -166 235 -100 133 -66 165 -102 133 -136 371 -162 1411 -132 865 -200 471 -100 133 -68 299 -66 633 -98 329 -234 401 -98 1505 -132 133 -134 331 -262 163 -66 261 -98 289 -64 201 -68 1055 -96 391 -66 951 -298 265 -202 297 -66 401 -68 131 -100 1733 -98 941 -66 803 -98 847 -64 3701 -100 721 -160 357 -166 1799 -66 329 -100 99 -102 363 -198 167 -136 197 -66 567 -66 199 -236 1247 -166 2455 -68 1107 -200 235 -100 2355 -130 913 -98 877 -98 163 -196 97 -66 427 -100 801 -134 867 -98 263 -68 441 -134 561 -98 1671 -134 865 -68 935 -132 163 -102 975 -66 1343 -132 1339 -134 369 -100 1107 -66 1167 -168 631 -232 835 -66 1027 -132 333 -166 265 -98 1207 -98 223 -98 455 -64 2095 -134 933 -136 233 -68 335 -136 305 -100 1737 -66 427 -100 263 -130 323 -66 227 -66 717 -100 265 -100 65 -128 355 -66 367 -132 95 -230 229 -100 131 -64 493 -132 291 -396 393 -130 259 -196 227 -288 397 -68 229 -430 99 -302 237 -700 65 -66 65 -100 133 -200 101 -336 133 -166 237 -202 67 -302 67 -68 333 -132 263 -102 267 -296 163 -166 233 -168 363 -64 295 -298 537 -166 431 -200 431 -166 63 -258 363 -164 563 -234 199 -68 299 -100 325 -754 295 -196 65 -98 165 -132 301 -134 131 -134 97 -68 405 -68 233 -134 271 -134 67 -168 101 -136 133 -366 99 -132 67 -132 265 -200 233 -100 201 -136 101 -66 263 -132 129 -66 293 -582 263 -132 1103 -134 203 -168 97 -66 197 -264 131 -168 133 -132 65 -134 199 -134 101 -100 131 -436 99 -232 97 -398 231 -362 65 -202 301 -396 297 -98 199 -134 265 -164 101 -168 267 -102 405 -170 99 -102 397 -132 97 -98 295 -98 1179 -100 135 -136 131 -134 765 -134 465 -168 439 -232 403 -100 65 -134 931 -100 169 -136 237 -68 231 -234 199 -68 401 -134 541 -166 429 -166 1607 -368 533 -66 363 -66 133 -134 433 -166 297 -238 201 -100 201 -170 199 -134 273 -136 99 -134 167 -238 133 -66 265 -134 165 -132 165 -132 97 -228 723 -198 415 -64 491 -298 257 -66 231 -192 225 -96 227 -98 193 -96 521 -198 65 -66 231 -166 163 -98 465 -66 133 -132 195 -130 225 -162 521 -130 63 -66 199 -228 +RAW_Data: 817 -162 449 -160 719 -198 469 -68 133 -68 1101 -132 593 -230 1105 -100 131 -134 231 -66 329 -196 685 -96 557 -68 1263 -68 101 -68 397 -100 65 -66 625 -66 97 -132 1099 -66 493 -66 757 -98 1151 -66 303 -134 1901 -66 99 -100 665 -262 991 -98 791 -66 1925 -168 865 -232 835 -98 505 -102 99 -100 535 -100 169 -134 427 -132 863 -68 167 -134 975 -100 133 -268 1339 -100 1453 -66 1445 -162 195 -64 3623 -66 237 -68 1063 -308 1449 -98 1111 -132 167 -102 855 -270 199 -134 297 -134 267 -168 863 -234 637 -66 567 -230 99 -200 3325 -198 845 -66 289 -66 131 -66 815 -130 1093 -100 167 -100 429 -98 1703 -166 195 -64 971 -98 163 -192 195 -168 439 -132 329 -132 67 -134 67 -134 1591 -168 407 -100 867 -68 399 -134 661 -100 663 -66 237 -136 395 -232 131 -66 695 -100 627 -264 913 -66 1083 -98 287 -66 199 -132 335 -100 1031 -68 99 -100 3815 -98 165 -66 129 -98 163 -128 563 -98 779 -96 223 -64 161 -164 2025 -66 1741 -172 101 -136 203 -102 665 -100 475 -64 167 -100 637 -98 997 -170 1207 -136 233 -166 233 -168 635 -132 199 -100 235 -270 199 -98 131 -102 169 -170 293 -98 323 -164 427 -334 233 -168 267 -68 369 -100 263 -368 101 -66 665 -98 265 -100 133 -100 99 -168 133 -66 133 -132 133 -66 269 -134 435 -68 267 -136 271 -500 163 -100 163 -166 355 -132 97 -98 323 -194 63 -688 463 -130 97 -396 65 -100 357 -194 461 -98 161 -130 223 -162 165 -352 461 -300 267 -166 233 -464 329 -100 293 -362 163 -228 289 -66 229 -66 195 -162 325 -66 261 -98 127 -424 299 -302 367 -68 265 -272 429 -98 161 -98 393 -296 65 -130 161 -196 261 -66 473 -234 97 -98 263 -160 323 -98 67 -132 697 -298 99 -134 233 -202 97 -134 301 -200 307 -100 101 -134 865 -166 231 -202 233 -100 301 -170 169 -102 169 -200 65 -98 595 -166 231 -234 661 -66 473 -334 165 -304 365 -266 97 -502 363 -134 133 -236 65 -100 99 -134 99 -170 235 -66 333 -100 195 -100 133 -300 133 -102 301 -304 65 -100 99 -100 131 -202 135 -134 65 -200 363 -66 263 -498 67 -68 295 -194 321 -368 435 -100 97 -664 99 -100 569 -66 133 -66 67 -134 199 -136 101 -68 301 -68 405 -198 133 -132 581 -132 165 -98 159 -98 197 -66 229 -130 131 -294 133 -96 423 -100 427 -300 357 -132 291 -64 95 -194 455 -98 263 -100 359 -196 65 -162 227 -162 157 -96 157 -230 589 -132 325 -134 535 -66 267 -100 135 -302 +RAW_Data: 131 -134 599 -166 393 -98 369 -236 197 -100 401 -232 569 -134 135 -70 337 -134 101 -136 135 -100 1895 -66 401 -170 503 -66 1633 -66 601 -66 355 -96 683 -100 729 -68 133 -132 433 -68 569 -100 133 -68 201 -132 835 -100 465 -68 527 -98 193 -200 1129 -166 535 -100 199 -98 259 -132 227 -64 1597 -98 261 -192 753 -100 911 -66 667 -298 131 -100 263 -66 1051 -230 787 -66 935 -66 233 -98 885 -236 431 -66 197 -162 521 -68 167 -196 263 -96 589 -98 517 -66 1439 -64 777 -66 3219 -132 679 -134 205 -68 507 -198 749 -200 199 -168 167 -100 133 -134 201 -68 731 -66 495 -198 737 -66 237 -68 135 -100 167 -234 1535 -68 873 -66 373 -66 67 -232 297 -68 65 -66 1095 -68 327 -130 63 -132 1715 -66 2261 -100 321 -132 197 -164 457 -232 1291 -132 405 -68 1001 -68 1133 -272 471 -66 99 -134 1403 -68 167 -68 1091 -336 933 -134 1207 -132 265 -68 267 -66 99 -366 265 -66 1469 -258 367 -168 429 -132 129 -66 491 -132 343 -100 65 -100 263 -136 199 -164 273 -204 791 -100 901 -66 167 -98 165 -64 559 -132 619 -132 1087 -128 2283 -398 1467 -164 259 -130 1927 -130 421 -98 1085 -66 705 -68 1843 -168 875 -170 203 -136 341 -640 199 -66 133 -554 161 -196 63 -66 521 -292 163 -160 95 -158 127 -192 197 -100 587 -130 397 -662 261 -66 193 -130 259 -66 361 -64 459 -98 197 -560 655 -130 389 -66 1135 -100 133 -130 131 -98 1011 -100 561 -66 685 -164 457 -132 2469 -200 609 -66 665 -66 67 -132 327 -200 1657 -134 919 -132 651 -100 327 -230 191 -130 263 -358 95 -130 549 -98 99 -68 299 -100 461 -132 99 -472 165 -134 99 -66 99 -132 399 -102 169 -102 697 -166 233 -132 333 -632 197 -164 865 -266 101 -68 533 -166 299 -100 163 -228 259 -66 327 -200 65 -66 229 -100 363 -230 197 -336 165 -102 893 -300 65 -132 231 -370 265 -230 99 -98 229 -518 199 -100 401 -724 225 -98 63 -96 231 -64 291 -292 65 -98 131 -98 159 -158 127 -194 161 -292 65 -98 133 -66 297 -66 303 -168 97 -168 231 -234 269 -532 135 -168 99 -168 301 -528 99 -506 199 -368 399 -132 329 -372 99 -68 133 -264 197 -100 201 -200 67 -134 131 -270 133 -134 133 -198 327 -200 65 -100 331 -262 161 -166 469 -534 167 -738 131 -100 367 -232 101 -100 265 -604 65 -170 99 -166 299 -102 169 -132 99 -398 229 -330 197 -166 335 -366 97 -98 131 -200 269 -100 199 -168 131 -134 537 -98 265 -100 335 -236 99 -366 +RAW_Data: 459 -100 453 -130 419 -130 519 -96 63 -130 2077 -66 767 -64 127 -134 1961 -296 529 -202 637 -134 527 -100 201 -68 633 -66 163 -360 1029 -68 765 -100 867 -66 503 -100 131 -66 841 -98 165 -68 237 -66 509 -100 501 -302 235 -66 99 -164 227 -130 551 -196 327 -66 1571 -132 99 -68 867 -66 163 -96 161 -130 129 -130 549 -130 487 -166 1801 -66 229 -66 197 -232 325 -66 425 -198 131 -64 295 -166 735 -66 533 -98 227 -130 129 -262 425 -100 263 -66 129 -132 97 -168 971 -170 405 -68 199 -134 475 -202 297 -98 1445 -98 395 -196 161 -66 225 -134 1803 -100 473 -102 1499 -66 199 -100 701 -132 165 -68 133 -102 303 -98 735 -102 805 -100 827 -100 235 -100 65 -266 637 -68 693 -66 1383 -228 819 -66 233 -304 435 -198 203 -136 1135 -270 1709 -64 227 -64 581 -134 505 -66 2203 -64 293 -64 753 -66 551 -132 747 -64 1303 -64 463 -66 229 -102 1877 -266 871 -166 1357 -64 819 -66 465 -198 693 -68 165 -64 95 -128 3785 -132 1465 -100 299 -102 329 -164 595 -134 1029 -66 299 -168 1263 -166 331 -68 967 -100 101 -102 603 -260 165 -132 467 -66 233 -66 235 -102 475 -100 135 -68 301 -134 297 -98 131 -102 269 -466 99 -134 237 -166 135 -168 203 -102 265 -68 503 -66 233 -66 637 -134 101 -200 199 -166 293 -554 361 -328 367 -264 533 -238 167 -68 135 -170 99 -300 591 -298 133 -236 299 -66 231 -368 263 -232 435 -136 133 -102 133 -200 133 -134 163 -134 167 -168 299 -66 265 -100 133 -240 135 -132 263 -170 269 -200 501 -396 263 -98 227 -132 129 -292 427 -66 165 -102 627 -602 99 -66 301 -168 199 -100 563 -330 165 -134 233 -136 65 -332 499 -100 131 -232 325 -96 65 -132 195 -98 393 -624 323 -68 133 -98 195 -162 231 -100 263 -132 231 -102 133 -236 99 -236 231 -166 65 -102 133 -268 101 -102 299 -136 267 -164 493 -64 229 -258 291 -326 263 -198 391 -134 167 -202 365 -594 133 -102 201 -134 503 -396 429 -204 169 -400 197 -170 267 -132 403 -466 297 -98 469 -234 395 -132 233 -100 165 -100 165 -66 197 -68 297 -166 501 -134 133 -100 65 -166 631 -68 297 -134 199 -100 165 -68 299 -266 133 -66 165 -100 231 -490 557 -134 371 -164 299 -170 733 -164 239 -334 335 -66 299 -300 199 -170 103 -100 233 -102 641 -168 65 -100 995 -66 265 -160 259 -130 129 -226 425 -100 355 -726 97 -688 99 -66 233 -266 299 -942 167 -102 167 -166 65 -100 367 -136 99 -134 199 -134 267 -164 +RAW_Data: 67 -68 233 -66 899 -66 163 -96 485 -98 355 -130 943 -100 235 -168 499 -104 1367 -98 297 -100 635 -68 1169 -100 67 -134 835 -264 959 -164 129 -98 419 -196 589 -66 421 -66 1717 -100 133 -100 265 -134 227 -356 455 -166 163 -66 1055 -100 1455 -134 463 -98 2191 -132 295 -132 335 -66 709 -64 619 -98 959 -68 835 -170 603 -134 1033 -134 635 -168 759 -232 397 -198 397 -164 1267 -166 257 -198 1295 -100 239 -104 563 -204 335 -198 203 -68 901 -68 1255 -134 1697 -66 793 -66 1691 -68 201 -100 765 -66 165 -132 131 -230 131 -66 917 -66 335 -338 231 -170 827 -98 199 -136 301 -196 65 -98 199 -200 765 -134 403 -98 333 -68 1691 -132 2565 -64 569 -170 1255 -264 65 -132 1243 -132 2527 -66 259 -66 1739 -100 1309 -198 167 -238 337 -66 131 -68 1973 -362 299 -100 1387 -96 129 -164 423 -230 3875 -96 4283 -98 165 -98 515 -134 469 -68 171 -102 1163 -100 65 -298 461 -66 367 -136 205 -168 371 -98 491 -164 161 -262 1093 -100 299 -100 269 -334 1205 -98 63 -98 261 -64 457 -98 diff --git a/assets/unit_tests/subghz/test_random_raw.sub b/assets/unit_tests/subghz/test_random_raw.sub index 928838d3..7d342bb9 100644 --- a/assets/unit_tests/subghz/test_random_raw.sub +++ b/assets/unit_tests/subghz/test_random_raw.sub @@ -145,3 +145,18 @@ RAW_Data: -66 133 -66 97 -166 561 -100 895 -132 1323 -66 10873 -3752 99 -722 229 RAW_Data: -5434 65 -298 133 -132 131 -68 231 -200 661 -132 9517 -424 97 -1456 99 -1694 393 -100 131 -560 131 -196 197 -298 65 -428 229 -196 297 -266 131 -166 2435 -66 10161 -11230 65 -1320 131 -298 265 -532 231 -200 1291 -68 631 -66 12645 -4048 133 -66 67 -132 167 -266 163 -66 397 -132 197 -132 299 -98 197 -198 2903 -66 2361 -66 9627 -3588 197 -332 165 -68 331 -68 197 -132 99 -100 663 -66 363 -230 231 -166 131 -100 201 -298 163 -132 133 -202 363 -300 397 -102 263 -100 165 -66 1221 -66 1479 -132 165 -98 229 -12976 263 -66 363 -134 231 -66 629 -132 327 -100 97 -130 99 -164 227 -64 297 -132 397 -164 425 -198 97 -198 99 -66 365 -164 199 -102 97 -66 1817 -13524 231 -134 16907 -4086 233 -630 65 -396 201 -66 165 -198 67 -198 99 -664 2117 -166 12473 -446 2649 -440 2661 -420 2651 -422 2681 -418 2703 -400 365 -2724 387 -2696 2695 -414 357 -2704 2707 -386 389 -2700 2687 -392 405 -2706 2695 -402 363 -21268 2707 -388 377 -2706 2691 -404 2699 -382 2717 -382 2707 -378 2693 -416 2687 -396 363 -2736 355 -2748 2659 -416 365 -2708 2715 -388 377 -2708 2697 -404 363 -2730 2673 -420 355 -21268 2655 -460 319 -2766 2663 -448 2631 -436 2665 -418 2683 -410 2681 -416 2701 -386 383 -2700 375 -2744 2669 -416 353 -2730 2685 -416 357 -2708 2721 -380 369 -2724 2697 -382 385 -21260 2701 -418 353 -2720 2673 -418 2675 -408 2693 -384 2715 -386 2717 -386 2691 -404 363 -2732 387 -2702 2669 -412 359 -2736 2699 -380 381 -2728 2675 -416 381 -2720 2675 -414 347 -21280 2685 -390 377 -2724 2689 -416 2673 -408 2705 -382 2695 -410 2689 -414 2661 -418 385 -2704 369 -2704 2693 -416 375 -2726 2661 -420 355 -2728 2711 -388 375 -2702 2691 -410 363 -21252 2659 -488 287 -2794 2651 -448 2629 -436 2671 -416 2695 -416 2663 -406 2699 -384 383 -2730 367 -2702 2695 -418 385 -2702 2685 -412 349 -2744 2693 -366 389 -2714 2693 -394 381 -21266 2685 -418 363 -2730 2683 -382 2693 -418 2675 -410 2699 -384 2719 -382 2707 -380 359 -2734 387 -2704 2709 -380 361 -2732 2699 -418 357 -2728 2667 -416 383 -2696 2709 -380 391 -21228 2685 -458 307 -2800 2647 -412 2659 -432 2667 -416 2695 -416 2675 -406 2675 -416 383 -2700 361 -2730 2687 -414 375 -2696 2701 -420 353 -2720 2711 -382 367 -2728 2675 -416 385 -21222 2735 -386 355 -2744 2687 -396 2679 -418 2701 -386 2705 -382 2681 -410 2697 -384 385 -2736 365 -2704 2715 -384 377 -2696 2697 -416 349 -2722 2707 -386 379 -2732 2671 -410 361 -21258 2681 -464 297 -2796 2629 -456 2655 -420 2661 -448 2663 -404 2695 -382 2715 -380 371 -2740 355 -2744 2679 -384 391 -2728 2675 -388 379 RAW_Data: -2728 2695 -414 357 -2704 2705 -418 357 -21262 2673 -416 383 -2696 2709 -380 2703 -384 2699 -418 2671 -408 2695 -382 2713 -386 379 -2730 357 -2732 2695 -384 383 -2730 2679 -416 357 -2708 2701 -410 349 -2736 2697 -382 385 -21252 2669 -478 289 -2790 2647 -426 2651 -444 2653 -430 2659 -418 2695 -414 2681 -402 349 -2738 383 -2722 2677 -414 347 -2744 2691 -382 369 -2730 2691 -384 383 -2734 2679 -414 347 -21264 2705 -386 379 -2736 2667 -410 2695 -382 2715 -380 2709 -420 2665 -392 2713 -382 383 -2730 365 -2728 2665 -418 383 -2696 2693 -418 357 -2710 2711 -380 375 -2718 2701 -416 357 -21238 2677 -484 311 -2766 2635 -444 2657 -420 2663 -422 2695 -416 2667 -428 2675 -396 363 -73890 133 -98 131 -132 129 -658 99 -66 853 -100 63 -100 361 -98 1589 -66 1231 -132 65 -100 297 -198 65 -132 265 -66 9857 -4672 165 -1030 97 -1394 65 -200 2687 -68 6873 -8336 99 -1156 97 -66 163 -232 163 -262 197 -132 295 -132 263 -166 953 -100 263 -130 393 -164 295 -64 329 -66 393 -164 823 -130 165 -66 6133 -8436 165 -164 265 -266 65 -362 197 -696 3181 -132 363 -98 65 -166 131 -66 399 -132 663 -396 329 -66 7335 -7578 497 -230 627 -264 99 -366 99 -132 131 -134 265 -498 163 -100 1323 -66 265 -66 1129 -100 399 -132 365 -100 795 -68 397 -98 597 -364 297 -132 361 -132 265 -132 8591 -4740 65 -100 131 -166 199 -1088 97 -296 99 -528 131 -98 661 -66 401 -198 1157 -166 361 -164 495 -100 165 -66 297 -100 1423 -66 3067 -5658 67 -6406 197 -1092 65 -530 659 -68 265 -100 991 -68 231 -230 297 -66 327 -66 131 -132 659 -134 131 -100 1183 -132 263 -98 621 -66 2075 -6976 65 -5138 67 -132 129 -664 67 -132 165 -100 331 -466 231 -68 467 -98 563 -66 231 -100 531 -66 465 -66 1023 -166 297 -134 3409 -12290 67 -164 99 -532 133 -166 263 -66 231 -66 721 -64 131 -68 959 -134 495 -100 299 -98 497 -98 365 -100 397 -232 297 -98 531 -66 3029 -12216 265 -132 99 -364 199 -234 131 -66 431 -166 333 -166 397 -132 327 -100 395 -66 197 -132 395 -66 527 -98 295 -100 97 -98 789 -132 363 -132 297 -200 2815 -4914 65 -6620 65 -462 65 -134 297 -66 497 -264 231 -198 2773 -134 365 -100 831 -166 131 -100 297 -132 861 -132 299 -100 561 -66 1381 -6946 65 -5516 231 -266 97 -1362 1093 -68 1621 -134 165 -332 297 -98 361 -228 97 -132 797 -98 3487 -13224 229 -164 65 -132 913 -66 1123 -98 527 -134 929 -98 723 -100 12259 -270 165 -132 67 -132 165 -1326 99 -98 65 -1194 431 -66 695 -66 733 -134 197 RAW_Data: -134 10801 -166 67 -6130 133 -198 231 -334 365 -98 229 -132 165 -68 231 -166 14501 -524 65 -328 131 -498 129 -1288 65 -494 163 -64 165 -66 527 -132 131 -132 1019 -198 129 -166 393 -198 65 -164 6411 -66 3255 -10642 65 -1320 165 -164 493 -492 559 -264 2555 -66 695 -66 1657 -164 855 -66 4001 -10526 97 -596 133 -298 67 -264 65 -300 65 -100 263 -166 231 -134 99 -100 2703 -68 13643 -4922 297 -100 65 -232 133 -198 331 -300 231 -66 331 -100 12047 -3872 97 -196 65 -494 329 -66 65 -890 97 -98 229 -164 195 -596 797 -66 861 -132 65 -66 231 -100 565 -66 65 -66 1297 -132 265 -66 363 -134 265 -364 297 -164 299 -134 297 -134 495 -98 11309 -3790 131 -1380 65 -758 65 -164 129 -460 65 -360 199 -100 563 -68 497 -198 363 -266 263 -100 165 -66 697 -66 1933 -13594 65 -762 1223 -132 1119 -196 361 -134 131 -100 793 -166 695 -68 231 -68 463 -66 11727 -4204 363 -264 131 -132 133 -1124 97 -100 163 -100 327 -100 331 -198 397 -66 397 -100 395 -100 163 -66 197 -564 1059 -7962 65 -100 65 -198 129 -362 99 -394 197 -296 495 -100 1357 -68 459 -66 593 -66 265 -68 301 -132 465 -66 231 -200 397 -66 397 -232 199 -298 12077 -4350 231 -796 363 -198 133 -264 65 -1132 597 -332 3295 -100 755 -98 231 -164 97 -264 459 -166 759 -164 3265 -12138 99 -232 99 -1228 1025 -100 393 -66 531 -132 693 -132 1063 -66 427 -64 297 -294 229 -98 9723 -5404 67 -466 99 -796 267 -98 201 -100 167 -264 461 -98 1415 -66 861 -66 267 -66 331 -134 1663 -66 2089 -7012 65 -100 101 -4804 431 -728 99 -100 65 -100 995 -134 165 -66 929 -100 65 -66 927 -100 1093 -168 99 -100 497 -66 665 -200 6517 -8312 165 -66 129 -66 559 -166 99 -430 65 -398 67 -66 593 -198 459 -132 261 -132 263 -130 723 -66 459 -100 325 -166 67 -198 559 -66 493 -66 11475 -3896 99 -266 99 -66 197 -1092 129 -198 361 -166 163 -98 263 -196 759 -100 265 -100 365 -630 4635 -12748 65 -1712 461 -100 497 -66 395 -98 265 -98 229 -164 529 -132 297 -66 565 -132 987 -132 8665 -2820 2265 -450 313 -2774 2643 -442 325 -2772 2665 -416 359 -2734 2667 -386 379 -21274 2657 -474 293 -2810 2619 -466 2613 -476 2629 -452 2663 -388 2683 -418 2705 -400 365 -2722 387 -2700 2697 -380 361 -2732 2691 -418 361 -2732 2667 -416 383 -2698 2697 -416 357 -21238 2715 -384 383 -2732 2685 -416 2667 -416 2695 -398 2671 -418 2687 -390 2713 -382 383 -2730 365 -2728 2661 -416 379 -2716 2685 -384 379 -2720 2703 -378 401 -2718 2671 +RAW_Data: 889 -130 325 -64 457 -560 165 -68 199 -170 67 -66 265 -132 133 -666 67 -166 431 -66 201 -98 297 -100 595 -66 199 -134 65 -100 795 -132 99 -168 501 -200 331 -132 265 -102 265 -134 423 -98 521 -226 65 -166 431 -134 99 -100 133 -464 195 -326 623 -100 673 -98 321 -200 65 -136 369 -166 65 -68 97 -166 165 -334 265 -102 231 -166 101 -170 65 -170 265 -136 931 -100 133 -134 563 -66 333 -100 427 -66 163 -390 231 -66 193 -130 461 -166 557 -100 99 -198 263 -100 197 -294 231 -232 299 -134 199 -170 267 -134 631 -98 235 -100 499 -68 463 -100 65 -134 335 -170 273 -134 297 -100 67 -66 197 -166 67 -134 301 -168 537 -470 99 -134 433 -132 199 -192 261 -100 523 -164 459 -132 259 -332 359 -64 227 -96 131 -132 687 -132 363 -136 329 -434 99 -334 133 -100 401 -132 233 -700 233 -170 337 -66 371 -68 233 -202 531 -266 731 -66 465 -100 167 -100 133 -232 335 -166 239 -102 367 -232 231 -100 167 -134 201 -136 301 -168 199 -300 231 -98 237 -134 233 -102 329 -132 261 -134 199 -66 265 -136 99 -170 167 -134 199 -166 167 -136 367 -298 197 -200 99 -166 469 -136 439 -66 303 -134 295 -100 433 -134 899 -266 363 -132 197 -160 555 -324 129 -96 97 -128 257 -132 97 -394 257 -98 195 -166 459 -332 395 -132 633 -134 301 -100 131 -332 169 -168 395 -166 263 -540 783 -100 287 -130 295 -96 225 -296 133 -98 99 -100 461 -164 545 -130 99 -66 301 -68 265 -100 235 -134 235 -70 333 -102 497 -66 233 -364 301 -170 103 -66 165 -336 733 -200 133 -100 263 -102 65 -136 465 -200 1035 -198 165 -170 67 -302 631 -100 429 -332 65 -128 129 -130 159 -128 159 -66 161 -96 325 -164 261 -100 197 -162 65 -96 99 -130 65 -102 333 -100 199 -98 389 -330 129 -128 229 -66 425 -366 229 -64 261 -100 227 -96 227 -526 301 -200 97 -66 699 -334 67 -100 399 -198 787 -98 297 -134 429 -100 3245 -64 527 -98 131 -526 633 -68 133 -302 1459 -164 971 -102 237 -136 1439 -266 1131 -66 599 -200 303 -332 325 -130 389 -166 371 -66 333 -102 65 -100 233 -234 327 -266 233 -166 297 -100 225 -130 163 -336 99 -596 199 -330 131 -66 331 -338 263 -358 197 -168 877 -66 227 -96 63 -130 263 -162 225 -290 197 -198 357 -132 297 -262 165 -456 227 -98 399 -296 95 -132 99 -98 457 -200 199 -168 535 -100 567 -134 327 -130 193 -130 683 -102 101 -132 233 -170 943 -166 827 -66 267 -102 503 -68 1325 -164 +RAW_Data: 1607 -68 233 -166 1167 -70 531 -134 335 -168 131 -66 299 -402 899 -66 461 -66 457 -98 953 -98 165 -66 293 -230 881 -64 393 -166 589 -66 289 -66 1093 -204 333 -98 2745 -132 2019 -170 925 -68 269 -102 1469 -136 2301 -68 1355 -100 527 -66 975 -68 1445 -98 2397 -100 1733 -66 703 -100 995 -100 135 -136 235 -202 167 -134 2071 -166 339 -170 201 -268 129 -66 465 -66 365 -100 197 -164 129 -98 161 -96 423 -66 675 -66 1543 -136 567 -200 767 -202 65 -100 1401 -66 623 -136 567 -234 67 -236 197 -194 97 -66 263 -66 1827 -392 1893 -98 165 -268 133 -132 231 -162 225 -98 695 -198 563 -100 301 -332 267 -102 341 -66 99 -132 1299 -130 525 -68 161 -96 357 -98 353 -100 131 -100 131 -98 163 -132 323 -100 535 -66 1323 -130 133 -66 235 -134 1497 -132 387 -98 129 -162 2623 -134 163 -68 167 -66 959 -232 495 -68 131 -134 867 -134 865 -66 333 -98 305 -134 231 -98 765 -198 397 -432 165 -66 165 -366 265 -102 541 -100 261 -162 331 -134 457 -66 491 -196 97 -266 193 -262 65 -166 231 -266 497 -360 263 -98 587 -164 259 -98 231 -66 359 -100 267 -102 271 -168 97 -262 63 -66 261 -130 227 -130 295 -164 65 -66 265 -200 597 -134 267 -170 603 -100 97 -466 231 -264 97 -168 99 -66 65 -200 199 -100 267 -404 303 -102 201 -204 235 -134 131 -198 335 -298 327 -130 291 -164 63 -162 295 -262 197 -130 95 -130 195 -96 159 -130 161 -66 231 -100 165 -66 199 -134 363 -66 267 -168 165 -168 167 -100 165 -530 363 -432 99 -232 65 -132 395 -328 229 -98 197 -132 161 -96 191 -292 197 -204 133 -100 399 -166 531 -332 235 -168 99 -66 325 -158 553 -132 129 -226 231 -134 99 -462 129 -64 289 -100 193 -66 355 -164 291 -198 131 -298 197 -198 373 -268 335 -234 427 -68 199 -132 267 -232 131 -66 783 -326 63 -162 161 -130 227 -66 259 -562 233 -464 303 -102 201 -334 301 -134 297 -198 229 -66 127 -166 99 -100 197 -198 571 -66 457 -134 361 -424 131 -328 163 -98 63 -100 505 -102 201 -1094 229 -164 65 -230 789 -236 2505 -166 201 -170 163 -64 1139 -66 927 -100 295 -198 723 -100 365 -66 459 -196 3033 -272 199 -66 499 -202 1319 -232 295 -298 131 -362 97 -164 129 -132 65 -98 197 -130 129 -98 261 -130 97 -98 229 -96 425 -66 227 -166 483 -66 163 -326 567 -68 235 -68 67 -66 167 -66 235 -330 425 -164 63 -66 427 -102 167 -66 669 -132 429 -200 65 -102 133 -100 197 -368 +RAW_Data: 65 -134 2481 -228 65 -130 229 -228 763 -136 603 -166 1619 -98 1763 -102 837 -166 321 -66 951 -130 2067 -66 259 -132 1835 -66 437 -102 701 -66 565 -68 363 -70 1113 -66 1989 -164 257 -128 351 -162 1055 -232 265 -170 309 -200 435 -166 833 -102 2467 -132 595 -66 773 -166 1615 -98 131 -96 485 -64 517 -166 197 -68 1231 -68 403 -100 263 -134 233 -100 503 -100 333 -266 729 -66 199 -100 369 -68 1239 -100 197 -68 299 -170 337 -100 825 -132 163 -66 4205 -64 161 -100 635 -66 907 -66 1017 -166 1709 -100 201 -266 657 -68 463 -166 331 -164 293 -64 259 -162 129 -262 597 -134 701 -136 67 -168 235 -136 303 -170 1417 -66 263 -98 857 -100 659 -166 97 -100 2497 -64 2495 -98 719 -128 227 -130 2217 -164 623 -264 719 -134 329 -98 1371 -100 553 -294 165 -66 1163 -100 329 -196 649 -200 1123 -68 263 -100 593 -266 333 -102 1133 -136 131 -132 603 -200 1819 -66 489 -66 563 -266 1113 -230 165 -66 423 -68 335 -100 101 -100 1073 -132 897 -100 101 -100 499 -134 173 -138 763 -238 371 -130 403 -166 203 -102 271 -136 269 -166 99 -168 263 -96 425 -66 331 -234 133 -400 231 -132 453 -66 459 -164 199 -68 237 -132 163 -198 161 -196 265 -132 65 -64 195 -130 357 -164 663 -68 167 -600 131 -98 133 -304 203 -134 433 -98 261 -130 199 -100 237 -100 229 -326 99 -98 331 -132 99 -294 165 -66 303 -134 99 -232 133 -136 99 -68 267 -198 233 -138 67 -166 367 -100 333 -168 267 -200 369 -266 135 -404 1939 -132 231 -160 161 -64 293 -98 331 -132 339 -104 135 -100 197 -430 263 -202 233 -64 195 -162 129 -64 227 -298 265 -68 697 -66 301 -68 231 -300 131 -368 769 -234 265 -98 195 -324 97 -752 229 -126 355 -98 257 -98 287 -64 427 -132 295 -262 197 -170 369 -102 267 -100 169 -68 201 -102 2551 -136 635 -134 639 -134 99 -132 197 -200 371 -66 731 -132 199 -138 733 -304 433 -68 729 -440 197 -68 99 -102 165 -266 261 -164 491 -296 489 -194 257 -164 133 -134 237 -68 335 -98 227 -130 229 -98 295 -98 231 -202 267 -236 233 -136 331 -130 195 -128 261 -430 261 -162 97 -224 99 -130 193 -96 197 -162 229 -396 97 -98 227 -364 267 -100 99 -100 233 -236 697 -164 227 -196 63 -98 327 -230 325 -66 129 -196 95 -98 195 -130 325 -430 131 -194 129 -454 161 -196 235 -68 433 -134 667 -164 355 -236 101 -98 2143 -134 1827 -198 63 -198 65 -64 2859 -64 619 -66 97 -130 3157 -66 679 -194 1491 -98 +RAW_Data: 951 -64 393 -100 955 -132 4715 -100 131 -66 199 -204 1541 -66 929 -130 1347 -166 665 -132 233 -132 67 -102 433 -100 595 -228 997 -66 505 -68 133 -98 231 -68 571 -134 1371 -232 231 -270 135 -102 97 -66 867 -100 269 -68 967 -100 1649 -66 65 -66 951 -68 65 -202 363 -200 779 -102 1449 -294 419 -130 361 -230 1079 -164 163 -260 893 -102 333 -100 533 -166 467 -100 135 -66 135 -202 369 -100 199 -100 269 -134 301 -166 229 -66 101 -134 199 -134 1293 -64 779 -62 831 -66 1243 -68 267 -102 197 -100 395 -98 455 -64 621 -132 877 -98 199 -100 2101 -134 503 -100 2035 -134 735 -236 475 -136 237 -132 133 -134 1229 -100 133 -66 167 -68 2655 -100 1807 -100 1095 -264 825 -98 163 -66 491 -98 161 -128 953 -100 773 -100 131 -66 67 -134 457 -130 63 -64 389 -98 715 -66 425 -300 97 -100 1515 -66 303 -68 99 -98 721 -64 887 -132 65 -132 165 -66 635 -68 2801 -66 1561 -100 751 -98 129 -64 725 -136 201 -100 333 -204 573 -104 1745 -134 99 -66 129 -64 595 -134 167 -102 337 -134 567 -134 1131 -138 1207 -100 269 -68 135 -100 1143 -134 2139 -68 1701 -162 991 -596 431 -66 99 -132 657 -66 391 -320 357 -260 259 -98 429 -66 163 -228 65 -130 227 -66 261 -166 99 -98 131 -366 199 -134 463 -102 201 -98 231 -102 639 -238 301 -568 169 -610 265 -102 841 -198 297 -100 335 -132 263 -266 265 -68 469 -134 267 -68 933 -298 333 -298 729 -168 135 -136 437 -132 1137 -134 199 -68 265 -132 463 -166 129 -130 227 -98 297 -98 65 -132 97 -202 199 -232 305 -66 165 -198 365 -66 99 -98 299 -170 65 -136 301 -232 99 -564 133 -132 233 -170 99 -102 131 -134 65 -204 101 -98 297 -98 167 -762 233 -298 99 -326 395 -66 299 -132 369 -504 333 -98 483 -200 457 -164 63 -164 329 -162 65 -622 231 -268 131 -132 133 -134 131 -134 131 -66 99 -100 231 -66 167 -336 165 -98 197 -100 97 -264 321 -98 521 -132 163 -130 129 -294 297 -134 101 -102 265 -168 497 -68 197 -68 499 -134 269 -398 267 -130 203 -302 65 -498 271 -136 465 -292 131 -294 163 -198 329 -96 129 -98 193 -130 391 -330 165 -134 167 -170 297 -102 133 -136 135 -366 199 -132 423 -132 395 -168 65 -166 401 -98 229 -98 329 -98 99 -130 129 -228 261 -160 127 -426 389 -162 193 -132 131 -100 231 -168 67 -304 201 -68 765 -132 161 -162 193 -64 195 -64 295 -130 787 -98 419 -528 429 -66 363 -134 131 -100 133 -200 331 -98 +RAW_Data: 431 -66 1167 -68 937 -68 1003 -66 99 -132 941 -134 65 -66 365 -274 165 -236 367 -96 557 -134 675 -66 261 -164 127 -96 391 -164 161 -98 391 -292 163 -98 519 -196 165 -98 523 -66 195 -160 3343 -66 661 -100 2589 -136 307 -100 629 -136 639 -100 133 -168 405 -100 267 -66 465 -132 1171 -64 749 -64 165 -98 983 -100 163 -202 537 -66 327 -100 669 -100 401 -236 2885 -164 439 -134 97 -426 1931 -66 1385 -98 715 -98 519 -66 289 -162 97 -360 297 -166 163 -66 289 -66 555 -334 167 -230 429 -102 267 -132 943 -136 401 -68 929 -130 193 -68 467 -198 335 -66 963 -100 597 -132 197 -260 523 -232 1115 -102 1935 -66 1395 -134 305 -100 99 -66 199 -66 1071 -66 2357 -66 367 -498 769 -234 163 -130 191 -64 1211 -200 133 -102 201 -100 561 -366 361 -98 195 -100 537 -64 165 -196 1041 -332 133 -102 441 -230 4217 -66 1033 -66 167 -66 933 -100 565 -66 331 -164 673 -104 441 -66 533 -66 2095 -164 525 -66 297 -170 965 -198 421 -100 663 -832 65 -100 331 -164 231 -166 135 -168 237 -466 761 -134 891 -196 791 -198 257 -160 161 -98 293 -66 1081 -98 229 -130 327 -66 1301 -200 331 -166 101 -66 461 -100 2619 -132 1663 -98 1609 -134 499 -332 165 -370 67 -264 97 -96 259 -98 701 -402 197 -128 527 -236 233 -102 167 -134 303 -134 99 -166 299 -132 165 -200 467 -68 305 -168 207 -102 465 -102 729 -136 101 -374 327 -96 259 -98 467 -202 65 -66 673 -98 335 -404 135 -66 339 -204 99 -366 233 -68 365 -166 133 -102 867 -198 163 -162 163 -294 463 -332 165 -68 269 -268 331 -100 131 -166 299 -132 231 -400 263 -164 131 -266 267 -264 367 -66 371 -134 229 -104 267 -232 67 -466 265 -100 101 -100 165 -200 65 -200 301 -66 199 -168 233 -98 267 -66 67 -134 261 -196 261 -234 427 -294 65 -194 193 -66 259 -132 849 -96 63 -198 167 -294 95 -98 361 -164 261 -196 131 -132 437 -100 597 -262 327 -162 295 -98 295 -164 259 -196 425 -230 321 -66 195 -66 261 -496 99 -200 529 -132 133 -966 133 -132 165 -66 63 -128 491 -402 65 -262 299 -66 299 -202 265 -100 99 -668 97 -134 65 -100 101 -66 65 -266 691 -66 431 -166 167 -134 199 -370 899 -134 99 -100 1093 -166 163 -166 399 -98 327 -100 99 -168 135 -200 133 -202 429 -98 65 -98 197 -556 65 -66 97 -326 331 -166 333 -200 135 -100 235 -234 265 -98 65 -68 135 -66 335 -66 133 -298 99 -66 233 -164 435 -232 97 -132 97 -392 +RAW_Data: 99 -198 819 -66 1235 -98 321 -132 1091 -66 1307 -98 3059 -164 3305 -64 227 -98 591 -98 129 -66 229 -98 2143 -98 939 -68 563 -100 361 -232 945 -164 257 -96 229 -230 387 -64 195 -130 981 -294 587 -162 193 -98 1337 -66 293 -98 2665 -66 297 -98 647 -66 459 -132 491 -164 489 -96 595 -66 899 -66 837 -64 1151 -196 259 -98 357 -164 891 -132 1359 -134 197 -98 97 -98 261 -64 229 -96 461 -136 693 -100 201 -98 865 -66 599 -100 517 -132 709 -66 293 -298 655 -66 197 -130 129 -66 197 -98 4291 -66 673 -66 667 -132 1473 -132 133 -104 99 -66 163 -168 333 -134 1743 -132 1097 -132 99 -68 167 -602 1323 -352 99 -166 753 -98 423 -98 97 -66 1317 -228 1309 -98 1849 -66 1939 -132 601 -100 665 -100 1875 -66 695 -132 425 -66 425 -66 263 -134 165 -134 99 -98 829 -66 601 -166 131 -102 565 -66 301 -100 1099 -100 601 -138 533 -66 667 -234 561 -66 99 -68 2741 -98 199 -100 531 -168 101 -434 1027 -68 431 -66 403 -132 99 -98 565 -132 135 -100 399 -166 271 -236 233 -166 197 -366 99 -66 99 -168 503 -66 199 -170 207 -100 673 -368 99 -66 263 -168 133 -98 397 -268 337 -66 131 -132 231 -132 501 -134 99 -168 567 -138 103 -136 267 -298 231 -134 197 -160 321 -332 231 -98 131 -164 257 -64 163 -328 395 -66 331 -202 65 -168 133 -68 167 -100 233 -102 335 -66 197 -326 1101 -132 589 -100 811 -132 399 -136 269 -102 497 -66 559 -100 129 -98 855 -68 637 -102 65 -200 875 -68 233 -166 167 -66 529 -202 235 -102 231 -66 1237 -66 733 -98 1723 -132 101 -100 297 -66 829 -232 197 -100 367 -134 169 -166 167 -434 633 -100 235 -200 131 -134 233 -100 131 -100 331 -134 495 -432 65 -528 161 -130 295 -132 337 -136 133 -166 165 -100 269 -240 201 -336 133 -166 165 -238 199 -202 431 -434 99 -134 501 -166 231 -96 559 -202 167 -66 717 -98 987 -198 65 -64 163 -64 227 -98 555 -164 199 -64 361 -66 163 -98 129 -162 97 -130 161 -460 197 -230 681 -98 197 -98 329 -100 267 -266 291 -264 65 -100 329 -100 459 -200 363 -98 165 -134 231 -134 301 -134 231 -302 99 -132 101 -134 267 -136 233 -68 393 -422 163 -166 361 -166 99 -134 365 -134 133 -336 401 -66 495 -132 401 -168 133 -402 501 -136 1093 -862 165 -132 293 -300 289 -66 131 -164 391 -134 99 -360 359 -130 323 -200 423 -98 195 -162 295 -132 161 -98 129 -782 131 -426 227 -64 259 -166 63 -160 323 -98 261 -230 +RAW_Data: 231 -66 921 -66 355 -64 1019 -98 227 -258 163 -66 597 -232 1313 -132 163 -404 467 -236 901 -164 483 -98 195 -96 489 -134 103 -238 169 -66 67 -68 299 -100 497 -68 65 -134 1635 -304 1153 -100 539 -168 265 -200 499 -166 535 -100 397 -168 931 -100 131 -66 631 -134 897 -270 1233 -100 65 -132 131 -334 663 -66 163 -66 131 -132 705 -98 571 -200 433 -100 237 -234 229 -132 1627 -66 569 -100 715 -66 1863 -272 265 -68 301 -98 465 -68 97 -134 99 -66 395 -136 1405 -66 529 -132 63 -196 579 -132 413 -260 129 -136 101 -166 1201 -134 833 -134 393 -66 335 -172 201 -68 1027 -96 753 -64 815 -66 97 -64 1341 -132 289 -160 127 -66 99 -228 1083 -96 163 -66 259 -64 159 -98 2409 -168 767 -200 367 -66 1675 -66 1067 -98 3407 -200 99 -66 1403 -166 99 -134 439 -200 329 -136 599 -66 637 -66 835 -66 1099 -98 99 -66 463 -166 165 -100 461 -164 3037 -66 655 -66 97 -98 229 -130 355 -132 1443 -66 527 -98 881 -98 229 -162 127 -96 583 -64 65 -162 489 -166 885 -194 257 -98 1539 -66 293 -166 229 -132 655 -98 757 -49522 271 -758 689 -1264 737 -670 293 -1152 811 -1144 341 -664 773 -678 327 -1118 807 -1144 835 -1146 781 -1126 873 -1096 347 -622 877 -624 321 -1106 843 -1098 871 -1098 843 -1106 379 -610 841 -584 381 -1122 365 -602 845 -1116 837 -610 381 -1056 889 -1078 383 -614 827 -1110 877 -592 353 -1108 845 -1120 839 -1120 347 -602 849 -1110 865 -612 361 -1072 869 -1114 351 -618 861 -618 343 -1090 853 -1106 387 -618 797 -674 347 -1084 389 -574 867 -584 381 -1114 841 -1102 845 -1116 839 -1112 843 -1098 875 -1086 383 -584 865 -588 375 -1100 861 -1112 851 -1084 853 -1108 847 -1106 381 -584 857 -610 383 -1080 357 -602 871 -602 385 -1084 383 -616 823 -610 373 -1086 381 -590 871 -1084 839 -628 353 -1102 875 -1100 349 -9404 875 -1060 871 -1086 887 -1088 879 -1058 863 -1086 855 -1132 845 -1078 871 -1076 857 -1098 881 -1082 861 -1088 843 -1120 853 -1074 879 -1074 879 -1068 889 -614 341 -1090 387 -616 863 -624 345 -1088 391 -590 857 -612 385 -1058 393 -596 843 -1088 889 -1078 879 -578 387 -1082 875 -1076 415 -550 881 -1070 877 -592 391 -1114 821 -1104 373 -620 821 -624 361 -1072 903 -1086 855 -1092 843 -1086 905 -1054 387 -614 863 -618 347 -1088 853 -1114 845 -1090 867 -1070 381 -610 885 -584 385 -1052 407 -578 877 -1052 899 -600 389 -1048 907 -1074 383 -586 877 -1072 877 -594 359 -1076 875 -1082 891 -1088 363 -616 855 -1084 857 -592 381 -1088 883 -1086 385 -572 +RAW_Data: 889 -624 353 -1082 853 -1096 379 -594 853 -624 353 -1092 417 -582 847 -612 385 -1076 847 -1080 883 -1052 913 -1044 907 -1076 849 -1088 383 -602 867 -616 361 -1068 901 -1072 865 -1104 831 -1080 879 -1098 397 -586 855 -626 355 -1084 381 -592 873 -616 351 -1084 385 -624 821 -620 359 -1086 387 -584 883 -1086 877 -592 355 -1106 853 -1086 387 -69570 97 -100 99 -2620 131 -636 333 -102 235 -236 67 -68 363 -66 201 -100 567 -102 267 -164 101 -134 65 -68 197 -68 297 -166 671 -100 469 -336 165 -100 201 -66 169 -230 169 -204 329 -624 67 -98 265 -232 193 -168 299 -100 235 -138 101 -370 165 -294 333 -622 231 -130 129 -130 353 -132 195 -162 359 -164 67 -68 333 -100 133 -688 235 -236 497 -198 293 -98 129 -296 293 -164 229 -128 229 -132 193 -400 165 -66 163 -98 361 -164 355 -196 587 -164 131 -98 263 -554 99 -130 129 -130 191 -464 99 -132 67 -100 167 -604 329 -66 199 -68 133 -102 163 -66 2971 -132 785 -66 329 -96 323 -100 201 -136 301 -66 1959 -166 867 -134 467 -66 297 -100 835 -100 753 -166 165 -64 67 -370 335 -66 559 -232 165 -334 65 -162 129 -354 163 -64 131 -134 265 -300 263 -132 267 -296 327 -198 99 -132 535 -132 469 -866 231 -860 99 -232 503 -134 99 -198 233 -134 267 -200 97 -358 297 -164 259 -98 227 -166 135 -66 323 -100 97 -294 131 -164 129 -98 295 -96 129 -426 299 -100 67 -102 623 -100 163 -194 127 -360 563 -134 199 -428 493 -98 229 -130 257 -64 165 -100 131 -98 163 -692 357 -64 161 -98 321 -64 389 -230 65 -692 227 -130 261 -132 231 -162 287 -298 97 -460 393 -130 301 -168 331 -100 269 -202 101 -134 201 -102 99 -132 199 -204 235 -664 65 -562 133 -328 463 -100 291 -194 159 -162 227 -98 293 -328 165 -128 227 -574 535 -332 197 -168 65 -300 131 -66 389 -1078 131 -64 259 -64 223 -98 257 -164 63 -328 433 -134 65 -602 131 -68 333 -136 369 -66 297 -264 427 -66 97 -130 429 -102 133 -136 203 -240 167 -236 329 -526 67 -132 133 -168 331 -360 65 -66 331 -296 267 -134 469 -132 595 -230 661 -662 299 -100 265 -200 203 -168 801 -100 133 -68 399 -132 99 -100 161 -390 65 -298 65 -98 261 -130 161 -128 257 -66 67 -134 621 -98 227 -328 99 -230 129 -294 193 -96 195 -318 425 -526 129 -196 163 -162 65 -132 293 -130 63 -66 325 -128 63 -130 293 -66 199 -200 269 -206 133 -198 325 -98 163 -100 97 -98 261 -164 67 -98 167 -430 131 -494 131 -164 +RAW_Data: 97 -98 861 -66 1199 -166 231 -100 651 -166 197 -104 439 -98 131 -64 493 -98 883 -96 99 -98 3327 -66 131 -264 733 -134 2133 -166 131 -102 303 -136 535 -134 701 -98 355 -228 131 -202 99 -134 99 -100 791 -166 169 -202 671 -100 741 -100 263 -66 165 -68 935 -132 197 -198 673 -100 605 -66 1457 -98 1195 -166 2347 -134 505 -100 1469 -66 391 -100 229 -100 1171 -98 939 -100 459 -170 369 -134 231 -162 127 -98 95 -66 195 -98 195 -66 299 -100 331 -98 65 -232 369 -132 201 -68 167 -166 1481 -102 501 -160 1257 -66 2307 -64 623 -164 2079 -66 1101 -98 423 -64 659 -68 431 -136 99 -100 435 -130 167 -168 835 -200 135 -104 133 -100 503 -68 1437 -232 821 -132 357 -96 463 -66 263 -64 683 -132 165 -96 655 -166 3939 -100 1169 -132 2443 -98 197 -132 425 -234 233 -162 1043 -66 197 -100 2793 -134 167 -104 675 -100 197 -134 1367 -102 763 -132 265 -230 133 -102 365 -100 167 -66 1069 -66 837 -100 295 -160 97 -64 129 -132 617 -164 197 -100 133 -136 337 -172 133 -66 557 -98 951 -66 263 -130 587 -66 729 -196 335 -166 933 -432 369 -100 199 -296 225 -98 355 -66 129 -64 557 -98 289 -66 355 -128 193 -162 267 -134 299 -98 165 -170 303 -640 1031 -134 99 -66 135 -68 771 -166 171 -104 201 -134 131 -68 635 -428 661 -292 749 -430 1161 -100 905 -98 65 -98 657 -262 2837 -132 67 -66 265 -132 631 -66 1037 -296 97 -98 1703 -302 367 -100 505 -232 497 -362 333 -134 591 -100 755 -232 67 -130 587 -66 231 -168 65 -332 99 -66 267 -232 393 -134 65 -132 131 -428 133 -200 165 -202 199 -168 165 -102 269 -100 333 -852 201 -134 233 -202 65 -200 563 -768 265 -136 169 -102 169 -598 333 -202 267 -134 267 -328 163 -130 625 -500 199 -200 99 -270 65 -134 65 -198 65 -100 99 -596 493 -66 99 -66 331 -232 103 -136 373 -168 831 -170 65 -672 163 -102 133 -136 331 -100 333 -234 101 -100 99 -200 99 -100 201 -302 199 -600 301 -202 135 -134 705 -166 435 -530 97 -198 131 -198 195 -66 163 -392 293 -66 295 -370 229 -198 65 -100 405 -134 165 -134 133 -170 337 -236 205 -274 267 -134 329 -132 195 -132 503 -132 133 -136 133 -334 197 -196 299 -168 101 -100 233 -100 439 -134 301 -332 331 -298 433 -406 433 -68 167 -100 203 -100 101 -102 99 -328 397 -234 205 -168 133 -364 63 -202 397 -198 95 -394 267 -134 569 -66 201 -102 133 -136 101 -102 99 -132 99 -196 197 -498 197 -102 135 -170 +RAW_Data: 331 -164 63 -162 1267 -66 163 -130 129 -66 725 -164 231 -64 853 -66 101 -134 199 -102 99 -68 365 -66 357 -130 815 -64 357 -98 97 -98 97 -66 65 -466 231 -172 3749 -66 849 -130 917 -64 327 -64 1013 -98 555 -332 795 -100 571 -132 769 -132 401 -134 1297 -134 377 -138 435 -100 401 -100 667 -100 1761 -66 667 -66 1533 -236 233 -98 885 -130 457 -66 999 -66 165 -66 833 -134 695 -166 501 -66 499 -200 329 -64 197 -134 441 -100 2099 -98 491 -134 197 -130 2225 -132 65 -100 689 -64 193 -160 159 -96 195 -98 323 -164 259 -98 535 -472 771 -66 665 -270 665 -66 595 -266 2191 -64 643 -98 1287 -98 741 -100 233 -200 569 -194 261 -68 637 -100 97 -66 491 -158 395 -138 1017 -66 627 -262 559 -64 327 -98 263 -134 99 -102 201 -102 337 -66 167 -68 679 -100 471 -134 195 -66 133 -202 693 -96 197 -98 391 -164 99 -98 3883 -194 461 -100 237 -168 1891 -68 301 -68 969 -166 1439 -294 551 -130 389 -98 99 -196 167 -102 505 -66 569 -234 901 -98 407 -136 469 -66 769 -98 769 -166 1263 -266 297 -98 1701 -200 203 -168 329 -232 65 -100 329 -164 803 -100 135 -200 233 -166 135 -272 265 -134 197 -100 133 -134 539 -232 197 -396 165 -366 263 -68 233 -102 365 -132 233 -100 135 -266 199 -234 167 -232 97 -524 127 -128 389 -98 305 -364 261 -130 257 -162 589 -464 361 -66 229 -134 161 -100 203 -432 265 -66 199 -66 199 -366 229 -236 99 -134 99 -100 131 -168 133 -100 131 -236 267 -132 297 -264 291 -132 167 -234 65 -100 199 -66 333 -730 237 -440 365 -102 99 -100 99 -132 99 -100 1429 -134 427 -100 97 -100 131 -164 799 -170 1077 -100 431 -66 133 -168 737 -134 197 -230 65 -102 803 -132 491 -98 429 -198 471 -134 365 -66 299 -236 65 -66 2837 -102 399 -64 585 -64 523 -196 97 -98 295 -196 555 -160 261 -500 299 -396 333 -236 133 -68 327 -100 199 -204 699 -66 701 -100 65 -164 65 -370 195 -196 97 -66 193 -130 129 -360 195 -130 231 -96 291 -64 455 -228 293 -196 291 -162 97 -194 621 -130 847 -66 395 -66 161 -128 193 -130 293 -98 231 -170 67 -134 297 -360 167 -266 263 -526 263 -132 229 -98 191 -160 159 -100 721 -234 101 -100 99 -130 259 -258 265 -632 687 -164 133 -134 631 -100 199 -102 165 -560 299 -200 265 -332 431 -870 99 -266 503 -364 135 -66 269 -68 499 -100 265 -102 263 -102 569 -234 719 -132 99 -196 419 -262 163 -688 95 -66 165 -128 95 -66 +RAW_Data: 295 -98 987 -196 517 -100 489 -66 355 -132 563 -198 867 -134 1413 -134 541 -134 767 -100 193 -98 1799 -102 467 -134 299 -96 323 -66 261 -100 259 -66 229 -96 851 -66 369 -266 469 -66 101 -98 163 -136 267 -432 859 -130 523 -66 197 -134 1027 -132 227 -194 393 -98 807 -166 235 -100 133 -66 165 -102 133 -136 371 -162 1411 -132 865 -200 471 -100 133 -68 299 -66 633 -98 329 -234 401 -98 1505 -132 133 -134 331 -262 163 -66 261 -98 289 -64 201 -68 1055 -96 391 -66 951 -298 265 -202 297 -66 401 -68 131 -100 1733 -98 941 -66 803 -98 847 -64 3701 -100 721 -160 357 -166 1799 -66 329 -100 99 -102 363 -198 167 -136 197 -66 567 -66 199 -236 1247 -166 2455 -68 1107 -200 235 -100 2355 -130 913 -98 877 -98 163 -196 97 -66 427 -100 801 -134 867 -98 263 -68 441 -134 561 -98 1671 -134 865 -68 935 -132 163 -102 975 -66 1343 -132 1339 -134 369 -100 1107 -66 1167 -168 631 -232 835 -66 1027 -132 333 -166 265 -98 1207 -98 223 -98 455 -64 2095 -134 933 -136 233 -68 335 -136 305 -100 1737 -66 427 -100 263 -130 323 -66 227 -66 717 -100 265 -100 65 -128 355 -66 367 -132 95 -230 229 -100 131 -64 493 -132 291 -396 393 -130 259 -196 227 -288 397 -68 229 -430 99 -302 237 -700 65 -66 65 -100 133 -200 101 -336 133 -166 237 -202 67 -302 67 -68 333 -132 263 -102 267 -296 163 -166 233 -168 363 -64 295 -298 537 -166 431 -200 431 -166 63 -258 363 -164 563 -234 199 -68 299 -100 325 -754 295 -196 65 -98 165 -132 301 -134 131 -134 97 -68 405 -68 233 -134 271 -134 67 -168 101 -136 133 -366 99 -132 67 -132 265 -200 233 -100 201 -136 101 -66 263 -132 129 -66 293 -582 263 -132 1103 -134 203 -168 97 -66 197 -264 131 -168 133 -132 65 -134 199 -134 101 -100 131 -436 99 -232 97 -398 231 -362 65 -202 301 -396 297 -98 199 -134 265 -164 101 -168 267 -102 405 -170 99 -102 397 -132 97 -98 295 -98 1179 -100 135 -136 131 -134 765 -134 465 -168 439 -232 403 -100 65 -134 931 -100 169 -136 237 -68 231 -234 199 -68 401 -134 541 -166 429 -166 1607 -368 533 -66 363 -66 133 -134 433 -166 297 -238 201 -100 201 -170 199 -134 273 -136 99 -134 167 -238 133 -66 265 -134 165 -132 165 -132 97 -228 723 -198 415 -64 491 -298 257 -66 231 -192 225 -96 227 -98 193 -96 521 -198 65 -66 231 -166 163 -98 465 -66 133 -132 195 -130 225 -162 521 -130 63 -66 199 -228 +RAW_Data: 817 -162 449 -160 719 -198 469 -68 133 -68 1101 -132 593 -230 1105 -100 131 -134 231 -66 329 -196 685 -96 557 -68 1263 -68 101 -68 397 -100 65 -66 625 -66 97 -132 1099 -66 493 -66 757 -98 1151 -66 303 -134 1901 -66 99 -100 665 -262 991 -98 791 -66 1925 -168 865 -232 835 -98 505 -102 99 -100 535 -100 169 -134 427 -132 863 -68 167 -134 975 -100 133 -268 1339 -100 1453 -66 1445 -162 195 -64 3623 -66 237 -68 1063 -308 1449 -98 1111 -132 167 -102 855 -270 199 -134 297 -134 267 -168 863 -234 637 -66 567 -230 99 -200 3325 -198 845 -66 289 -66 131 -66 815 -130 1093 -100 167 -100 429 -98 1703 -166 195 -64 971 -98 163 -192 195 -168 439 -132 329 -132 67 -134 67 -134 1591 -168 407 -100 867 -68 399 -134 661 -100 663 -66 237 -136 395 -232 131 -66 695 -100 627 -264 913 -66 1083 -98 287 -66 199 -132 335 -100 1031 -68 99 -100 3815 -98 165 -66 129 -98 163 -128 563 -98 779 -96 223 -64 161 -164 2025 -66 1741 -172 101 -136 203 -102 665 -100 475 -64 167 -100 637 -98 997 -170 1207 -136 233 -166 233 -168 635 -132 199 -100 235 -270 199 -98 131 -102 169 -170 293 -98 323 -164 427 -334 233 -168 267 -68 369 -100 263 -368 101 -66 665 -98 265 -100 133 -100 99 -168 133 -66 133 -132 133 -66 269 -134 435 -68 267 -136 271 -500 163 -100 163 -166 355 -132 97 -98 323 -194 63 -688 463 -130 97 -396 65 -100 357 -194 461 -98 161 -130 223 -162 165 -352 461 -300 267 -166 233 -464 329 -100 293 -362 163 -228 289 -66 229 -66 195 -162 325 -66 261 -98 127 -424 299 -302 367 -68 265 -272 429 -98 161 -98 393 -296 65 -130 161 -196 261 -66 473 -234 97 -98 263 -160 323 -98 67 -132 697 -298 99 -134 233 -202 97 -134 301 -200 307 -100 101 -134 865 -166 231 -202 233 -100 301 -170 169 -102 169 -200 65 -98 595 -166 231 -234 661 -66 473 -334 165 -304 365 -266 97 -502 363 -134 133 -236 65 -100 99 -134 99 -170 235 -66 333 -100 195 -100 133 -300 133 -102 301 -304 65 -100 99 -100 131 -202 135 -134 65 -200 363 -66 263 -498 67 -68 295 -194 321 -368 435 -100 97 -664 99 -100 569 -66 133 -66 67 -134 199 -136 101 -68 301 -68 405 -198 133 -132 581 -132 165 -98 159 -98 197 -66 229 -130 131 -294 133 -96 423 -100 427 -300 357 -132 291 -64 95 -194 455 -98 263 -100 359 -196 65 -162 227 -162 157 -96 157 -230 589 -132 325 -134 535 -66 267 -100 135 -302 +RAW_Data: 131 -134 599 -166 393 -98 369 -236 197 -100 401 -232 569 -134 135 -70 337 -134 101 -136 135 -100 1895 -66 401 -170 503 -66 1633 -66 601 -66 355 -96 683 -100 729 -68 133 -132 433 -68 569 -100 133 -68 201 -132 835 -100 465 -68 527 -98 193 -200 1129 -166 535 -100 199 -98 259 -132 227 -64 1597 -98 261 -192 753 -100 911 -66 667 -298 131 -100 263 -66 1051 -230 787 -66 935 -66 233 -98 885 -236 431 -66 197 -162 521 -68 167 -196 263 -96 589 -98 517 -66 1439 -64 777 -66 3219 -132 679 -134 205 -68 507 -198 749 -200 199 -168 167 -100 133 -134 201 -68 731 -66 495 -198 737 -66 237 -68 135 -100 167 -234 1535 -68 873 -66 373 -66 67 -232 297 -68 65 -66 1095 -68 327 -130 63 -132 1715 -66 2261 -100 321 -132 197 -164 457 -232 1291 -132 405 -68 1001 -68 1133 -272 471 -66 99 -134 1403 -68 167 -68 1091 -336 933 -134 1207 -132 265 -68 267 -66 99 -366 265 -66 1469 -258 367 -168 429 -132 129 -66 491 -132 343 -100 65 -100 263 -136 199 -164 273 -204 791 -100 901 -66 167 -98 165 -64 559 -132 619 -132 1087 -128 2283 -398 1467 -164 259 -130 1927 -130 421 -98 1085 -66 705 -68 1843 -168 875 -170 203 -136 341 -640 199 -66 133 -554 161 -196 63 -66 521 -292 163 -160 95 -158 127 -192 197 -100 587 -130 397 -662 261 -66 193 -130 259 -66 361 -64 459 -98 197 -560 655 -130 389 -66 1135 -100 133 -130 131 -98 1011 -100 561 -66 685 -164 457 -132 2469 -200 609 -66 665 -66 67 -132 327 -200 1657 -134 919 -132 651 -100 327 -230 191 -130 263 -358 95 -130 549 -98 99 -68 299 -100 461 -132 99 -472 165 -134 99 -66 99 -132 399 -102 169 -102 697 -166 233 -132 333 -632 197 -164 865 -266 101 -68 533 -166 299 -100 163 -228 259 -66 327 -200 65 -66 229 -100 363 -230 197 -336 165 -102 893 -300 65 -132 231 -370 265 -230 99 -98 229 -518 199 -100 401 -724 225 -98 63 -96 231 -64 291 -292 65 -98 131 -98 159 -158 127 -194 161 -292 65 -98 133 -66 297 -66 303 -168 97 -168 231 -234 269 -532 135 -168 99 -168 301 -528 99 -506 199 -368 399 -132 329 -372 99 -68 133 -264 197 -100 201 -200 67 -134 131 -270 133 -134 133 -198 327 -200 65 -100 331 -262 161 -166 469 -534 167 -738 131 -100 367 -232 101 -100 265 -604 65 -170 99 -166 299 -102 169 -132 99 -398 229 -330 197 -166 335 -366 97 -98 131 -200 269 -100 199 -168 131 -134 537 -98 265 -100 335 -236 99 -366 +RAW_Data: 459 -100 453 -130 419 -130 519 -96 63 -130 2077 -66 767 -64 127 -134 1961 -296 529 -202 637 -134 527 -100 201 -68 633 -66 163 -360 1029 -68 765 -100 867 -66 503 -100 131 -66 841 -98 165 -68 237 -66 509 -100 501 -302 235 -66 99 -164 227 -130 551 -196 327 -66 1571 -132 99 -68 867 -66 163 -96 161 -130 129 -130 549 -130 487 -166 1801 -66 229 -66 197 -232 325 -66 425 -198 131 -64 295 -166 735 -66 533 -98 227 -130 129 -262 425 -100 263 -66 129 -132 97 -168 971 -170 405 -68 199 -134 475 -202 297 -98 1445 -98 395 -196 161 -66 225 -134 1803 -100 473 -102 1499 -66 199 -100 701 -132 165 -68 133 -102 303 -98 735 -102 805 -100 827 -100 235 -100 65 -266 637 -68 693 -66 1383 -228 819 -66 233 -304 435 -198 203 -136 1135 -270 1709 -64 227 -64 581 -134 505 -66 2203 -64 293 -64 753 -66 551 -132 747 -64 1303 -64 463 -66 229 -102 1877 -266 871 -166 1357 -64 819 -66 465 -198 693 -68 165 -64 95 -128 3785 -132 1465 -100 299 -102 329 -164 595 -134 1029 -66 299 -168 1263 -166 331 -68 967 -100 101 -102 603 -260 165 -132 467 -66 233 -66 235 -102 475 -100 135 -68 301 -134 297 -98 131 -102 269 -466 99 -134 237 -166 135 -168 203 -102 265 -68 503 -66 233 -66 637 -134 101 -200 199 -166 293 -554 361 -328 367 -264 533 -238 167 -68 135 -170 99 -300 591 -298 133 -236 299 -66 231 -368 263 -232 435 -136 133 -102 133 -200 133 -134 163 -134 167 -168 299 -66 265 -100 133 -240 135 -132 263 -170 269 -200 501 -396 263 -98 227 -132 129 -292 427 -66 165 -102 627 -602 99 -66 301 -168 199 -100 563 -330 165 -134 233 -136 65 -332 499 -100 131 -232 325 -96 65 -132 195 -98 393 -624 323 -68 133 -98 195 -162 231 -100 263 -132 231 -102 133 -236 99 -236 231 -166 65 -102 133 -268 101 -102 299 -136 267 -164 493 -64 229 -258 291 -326 263 -198 391 -134 167 -202 365 -594 133 -102 201 -134 503 -396 429 -204 169 -400 197 -170 267 -132 403 -466 297 -98 469 -234 395 -132 233 -100 165 -100 165 -66 197 -68 297 -166 501 -134 133 -100 65 -166 631 -68 297 -134 199 -100 165 -68 299 -266 133 -66 165 -100 231 -490 557 -134 371 -164 299 -170 733 -164 239 -334 335 -66 299 -300 199 -170 103 -100 233 -102 641 -168 65 -100 995 -66 265 -160 259 -130 129 -226 425 -100 355 -726 97 -688 99 -66 233 -266 299 -942 167 -102 167 -166 65 -100 367 -136 99 -134 199 -134 267 -164 +RAW_Data: 67 -68 233 -66 899 -66 163 -96 485 -98 355 -130 943 -100 235 -168 499 -104 1367 -98 297 -100 635 -68 1169 -100 67 -134 835 -264 959 -164 129 -98 419 -196 589 -66 421 -66 1717 -100 133 -100 265 -134 227 -356 455 -166 163 -66 1055 -100 1455 -134 463 -98 2191 -132 295 -132 335 -66 709 -64 619 -98 959 -68 835 -170 603 -134 1033 -134 635 -168 759 -232 397 -198 397 -164 1267 -166 257 -198 1295 -100 239 -104 563 -204 335 -198 203 -68 901 -68 1255 -134 1697 -66 793 -66 1691 -68 201 -100 765 -66 165 -132 131 -230 131 -66 917 -66 335 -338 231 -170 827 -98 199 -136 301 -196 65 -98 199 -200 765 -134 403 -98 333 -68 1691 -132 2565 -64 569 -170 1255 -264 65 -132 1243 -132 2527 -66 259 -66 1739 -100 1309 -198 167 -238 337 -66 131 -68 1973 -362 299 -100 1387 -96 129 -164 423 -230 3875 -96 4283 -98 165 -98 515 -134 469 -68 171 -102 1163 -100 65 -298 461 -66 367 -136 205 -168 371 -98 491 -164 161 -262 1093 -100 299 -100 269 -334 1205 -98 63 -98 261 -64 457 -98 diff --git a/debug/flipperapps.py b/debug/flipperapps.py new file mode 100644 index 00000000..c8d3fcdb --- /dev/null +++ b/debug/flipperapps.py @@ -0,0 +1,157 @@ +from dataclasses import dataclass +from typing import Tuple, Dict +import struct +import posixpath +import os +import zlib + +import gdb + + +def get_file_crc32(filename): + with open(filename, "rb") as f: + return zlib.crc32(f.read()) + + +@dataclass +class AppState: + name: str + text_address: int = 0 + entry_address: int = 0 + other_sections: Dict[str, int] = None + debug_link_elf: str = "" + debug_link_crc: int = 0 + + def __post_init__(self): + if self.other_sections is None: + self.other_sections = {} + + def get_original_elf_path(self, elf_path="build/latest/.extapps") -> str: + return ( + posixpath.join(elf_path, self.debug_link_elf) + if elf_path + else self.debug_link_elf + ) + + def is_debug_available(self) -> bool: + have_debug_info = bool(self.debug_link_elf and self.debug_link_crc) + if not have_debug_info: + print("No debug info available for this app") + return False + debug_elf_path = self.get_original_elf_path() + debug_elf_crc32 = get_file_crc32(debug_elf_path) + if self.debug_link_crc != debug_elf_crc32: + print( + f"Debug info ({debug_elf_path}) CRC mismatch: {self.debug_link_crc:08x} != {debug_elf_crc32:08x}, rebuild app" + ) + return False + return True + + def get_gdb_load_command(self) -> str: + load_path = self.get_original_elf_path() + print(f"Loading debug information from {load_path}") + load_command = ( + f"add-symbol-file -readnow {load_path} 0x{self.text_address:08x} " + ) + load_command += " ".join( + f"-s {name} 0x{address:08x}" + for name, address in self.other_sections.items() + ) + return load_command + + def get_gdb_unload_command(self) -> str: + return f"remove-symbol-file -a 0x{self.text_address:08x}" + + def is_loaded_in_gdb(self, gdb_app) -> bool: + # Avoid constructing full app wrapper for comparison + return self.entry_address == int(gdb_app["entry"]) + + @staticmethod + def parse_debug_link_data(section_data: bytes) -> Tuple[str, int]: + # Debug link format: a null-terminated string with debuggable file name + # Padded with 0's to multiple of 4 bytes + # Followed by 4 bytes of CRC32 checksum of that file + elf_name = section_data[:-4].decode("utf-8").split("\x00")[0] + crc32 = struct.unpack(" "AppState": + state = AppState(str(gdb_app["manifest"]["name"].string())) + state.entry_address = int(gdb_app["entry"]) + + app_state = gdb_app["state"] + if debug_link_size := int(app_state["debug_link_size"]): + debug_link_data = ( + gdb.selected_inferior() + .read_memory(int(app_state["debug_link"]), debug_link_size) + .tobytes() + ) + state.debug_link_elf, state.debug_link_crc = AppState.parse_debug_link_data( + debug_link_data + ) + + for idx in range(app_state["mmap_entry_count"]): + mmap_entry = app_state["mmap_entries"][idx] + section_name = mmap_entry["name"].string() + section_addr = int(mmap_entry["address"]) + if section_name == ".text": + state.text_address = section_addr + else: + state.other_sections[section_name] = section_addr + + return state + + +class FlipperAppDebugHelper: + def __init__(self): + self.app_ptr = None + self.app_type_ptr = None + self.current_app: AppState = None + + def attach_fw(self) -> None: + self.app_ptr = gdb.lookup_global_symbol("last_loaded_app") + self.app_type_ptr = gdb.lookup_type("FlipperApplication").pointer() + self._check_app_state() + + def _check_app_state(self) -> None: + app_ptr_value = self.app_ptr.value() + if not app_ptr_value and self.current_app: + # There is an ELF loaded in GDB, but nothing is running on the device + self._unload_debug_elf() + elif app_ptr_value: + # There is an app running on the device + loaded_app = app_ptr_value.cast(self.app_type_ptr).dereference() + + if self.current_app and not self.current_app.is_loaded_in_gdb(loaded_app): + # Currently loaded ELF is not the one running on the device + self._unload_debug_elf() + + if not self.current_app: + # Load ELF for the app running on the device + self._load_debug_elf(loaded_app) + + def _unload_debug_elf(self) -> None: + try: + gdb.execute(self.current_app.get_gdb_unload_command()) + except gdb.error as e: + print(f"Failed to unload debug ELF: {e} (might not be an error)") + self.current_app = None + + def _load_debug_elf(self, app_object) -> None: + self.current_app = AppState.from_gdb(app_object) + + if self.current_app.is_debug_available(): + gdb.execute(self.current_app.get_gdb_load_command()) + + def handle_stop(self, event) -> None: + self._check_app_state() + + +helper = FlipperAppDebugHelper() +try: + helper.attach_fw() + print("Support for Flipper external apps debug is enabled") + gdb.events.stop.connect(helper.handle_stop) +except gdb.error as e: + print(f"Support for Flipper external apps debug is not available: {e}") diff --git a/documentation/AppManifests.md b/documentation/AppManifests.md index 7b117789..7bc8d0a4 100644 --- a/documentation/AppManifests.md +++ b/documentation/AppManifests.md @@ -1,3 +1,82 @@ # Flipper Application Manifests (.fam) -TBD \ No newline at end of file +All components of Flipper Zero firmware — services, user applications, system settings — are developed independently. Each component has a build system manifest file, named `application.fam`, which defines basic properties of that component and its relations to other parts of the system. + +When building firmware, **`fbt`** collects all application manifests and processes their dependencies. Then it builds only those components that are referenced in the current build configuration. See [fbt docs](./fbt.md#firmware-application-set) for details on build configurations. + +## Application definition + +Properties of a firmware component are declared in a form of a Python code snippet, forming a call to App() function with various parameters. + +Only 2 parameters are mandatory: ***appid*** and ***apptype***, others are optional and may only be meaningful for certain application types. + +### Parameters + +* **appid**: string, application id within the build system. Used for specifying which applications to include in build configuration and to resolve dependencies and conflicts. + +* **apptype**: member of FlipperAppType.* enumeration. Valid values are: + +| Enum member | Firmware component type | +|--------------|--------------------------| +| SERVICE | System service, created at early startup | +| SYSTEM | Application not being shown in any menus. Can be started by other apps or from CLI | +| APP | Regular application for main menu | +| PLUGIN | Application to be built as a part of firmware an to be placed in Plugins menu | +| DEBUG | Application only visible in Debug menu with debug mode enabled | +| ARCHIVE | One and only Archive app | +| SETTINGS | Application to be placed in System settings menu | +| STARTUP | Callback function to run at system startup. Does not define a separate app | +| EXTERNAL | Application to be built as .fap plugin | +| METAPACKAGE | Does not define any code to be run, used for declaring dependencies and application bundles | + +* **name**: Name that is displayed in menus. +* **entry_point**: C function to be used as application's entry point. +* **flags**: Internal flags for system apps. Do not use. +* **cdefines**: C preprocessor definitions to declare globally for other apps when current application is included in active build configuration. +* **requires**: List of application IDs to also include in build configuration, when current application is referenced in list of applications to build. +* **conflicts**: List of application IDs that current application conflicts with. If any of them is found in constructed application list, **`fbt`** will abort firmware build process. +* **provides**: Functionally identical to ***requires*** field. +* **stack_size**: Stack size, in bytes, to allocate for application on its startup. Note that allocating a stack that is too small for an app to run will cause system crash due to stack overflow, and allocating too much stack space will reduce usable heap memory size for apps to process data. *Note: you can use `ps` and `free` CLI commands to profile your app's memory usage.* +* **icon**: Animated icon name from built-in assets to be used when building app as a part of firmware. +* **order**: Order of an application within its group when sorting entries in it. The lower the order is, the closer to the start of the list the item is placed. *Used for ordering startup hooks and menu entries.* +* **sdk_headers**: List of C header files from this app's code to include in API definitions for external applications. + +The following parameters are used only for [FAPs](./AppsOnSDCard.md): + +* **sources**: list of file name masks, used for gathering sources within app folder. Default value of ["\*.c\*"] includes C and CPP source files. +* **fap_version**: string, 2 numbers in form of "x.y": application version to be embedded within .fap file. +* **fap_icon**: name of a .png file, 1-bit color depth, 10x10px, to be embedded within .fap file. +* **fap_libs**: list of extra libraries to link application against. Provides access to extra functions that are not exported as a part of main firmware at expense of increased .fap file size and RAM consumption. +* **fap_category**: string, may be empty. App subcategory, also works as path of FAP within apps folder in the file system. +* **fap_description**: string, may be empty. Short application descriotion. +* **fap_author**: string, may be empty. Application's author. +* **fap_weburl**: string, may be empty. Application's homepage. + + +## .fam file contents + +.fam file contains one or more Application definitions. For example, here's a part of `applications/service/bt/application.fam`: + +```python +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, +) +``` + +For more examples, see .fam files from various firmware parts. diff --git a/documentation/AppsOnSDCard.md b/documentation/AppsOnSDCard.md new file mode 100644 index 00000000..52582153 --- /dev/null +++ b/documentation/AppsOnSDCard.md @@ -0,0 +1,72 @@ +# FAP (Flipper Application Package) + +[fbt](./fbt.md) has support for building applications as FAP files. FAP are essentially .elf executables with extra metadata and resources bundled in. + +FAPs are built with `firmware_extapps` (or `plugin_dist`) **`fbt`** targets. + +FAPs do not depend on being run on a specific firmware version. Compatibility is determined by the FAP's metadata, which includes the required [API version](#api-versioning). + + +## How to set up an application to be built as a FAP + +FAPs are created and developed the same way as internal applications that are part of the firmware. + +To build your application as a FAP, just create a folder with your app's source code in `applications_user`, then write its code the way you'd do when creating a regular built-in application. Then configure its `application.fam` manifest — and set its *apptype* to FlipperAppType.EXTERNAL. See [Application Manifests](./AppManifests.md#application-definition) for more details. + + * To build your application, run `./fbt firmware_{APPID}`, where APPID is your application's ID in its manifest. + * To build your app, then upload it over USB & run it on Flipper, use `./fbt launch_app APPSRC=applications/path/to/app`. This command is configured in default [VSCode profile](../.vscode/ReadMe.md) as "Launch App on Flipper" build action (Ctrl+Shift+B menu). + * To build all FAPs, run `./fbt plugin_dist`. + + +## Debugging FAPs + +**`fbt`** includes a script for gdb-py to provide debugging support for FAPs, `debug/flipperapps.py`. It is loaded in default debugging configurations by **`fbt`** and stock VSCode configurations. + +With it, you can debug FAPs as if they were a part of main firmware — inspect variables, set breakpoints, step through the code, etc. + +### Setting up debugging environment + +Debugging support script looks up debugging information in latest firmware build dir (`build/latest`). That directory is symlinked by fbt to the latest firmware configuration (Debug or Release) build dir, when you run `./fbt` for chosen configuration. See [fbt docs](./fbt.md#nb) for details. + +So, to debug FAPs, do the following: +1. Build firmware with `./fbt` +2. Flash it with `./fbt flash` +3. [Build your FAP](#how-to-set-up-an-application-to-be-built-as-a-fap) and run it on Flipper. + +After that, you can attach with `./fbt debug` or VSCode and use all debug features. + +It is **important** that firmware and application build type (debug/release) match, and that matching firmware folder is linked as `build/latest`. Otherwise, debugging will not work. + + +## How Flipper runs an application from SD card + +Flipper's MCU cannot run code directly from external storage, so it needs to be copied to RAM first. That is done by the App Loader application, which is responsible for loading the FAP from SD card, verifying its integrity and compatibility, copying it to RAM and adjusting it for its new location. + +Since FAP has to be loaded to RAM to be executed, the amount of RAM available for allocations from heap is reduced compared to running the same app from flash, as a part of firmware. Note that the amount of occupied RAM is less than total FAP file size, since only code and data sections are allocated, while FAP file includes extra information only used at app load time. + +Applications are built for a specific API version. It is a part of the hardware target's definition and contains a major and minor version number. Application loader checks if the application's major API version matches firmware's major API version. + +App loader allocates memory for the application and copies it to RAM, processing relocations and providing concrete addresses for imported symbols using the [symbol table](#symbol-table). Then it starts the application. + + +## API Versioning + +Not all parts of firmware are available for external applications. A subset of available functions and variables is defined in "api_symbols.csv" file, which is a part of firmware target definition in `firmware/targets/` directory. + +**`fbt`** uses semantic versioning for API versioning. Major version is incremented when there are breaking changes in the API, minor version is incremented when there are new features added. + +Breaking changes include: +- removal of a function or a global variable; +- changing the signature of a function. + +API versioning is mostly automated by **`fbt`**. When rebuilding the firmware, **`fbt`** checks if there are any changes in the API exposed by headers gathered from `SDK_HEADERS`. If there are, it stops the build, adjusts the API version and asks the user to go through the changes in .csv file. New entries are marked with "`?`" mark, and the user is supposed to change the mark to "`+`" for the entry to be exposed for FAPs, "`-`" for it to be unavailable. + +**`fbt`** will not allow building a firmware until all "`?`" entries are changed to "`+`" or "`-`". + +**NB:** **`fbt`** automatically manages the API version. The only case where manually incrementing the major API version is allowed (and required) is when existing "`+`" entries are to be changed to "`-`". + +### Symbol Table + +The symbol table is a list of symbols exported by firmware and available for external applications. It is generated by **`fbt`** from the API symbols file and is used by the App Loader to resolve addresses of imported symbols. It is build as a part of the `fap_loader` application. + +**`fbt`** also checks if all imported symbols are present in the symbol table. If there are any missing symbols, it will issue a warning listing them. Such application won't be able to run on the device until all requires symbols are provided in the symbol table. diff --git a/documentation/OTA.md b/documentation/OTA.md index 2a6b0984..836bc1b7 100644 --- a/documentation/OTA.md +++ b/documentation/OTA.md @@ -1,8 +1,8 @@ # Executing code from RAM -In Flipper firmware, we have a special boot mode that loads a specially crafted system image into RAM and transfers control to it. System image executing in RAM has full write access to whole Flipper's flash memory — something that's not possible when running main code from same flash. +In Flipper firmware, we have a special boot mode that loads a specially crafted system image into RAM and transfers control to it. System image executing in RAM has full write access to whole Flipper's flash memory — something that's not possible when running main code from the same flash. -We leverage that boot mode to perform OTA firmware updates, including operations on radio stack running on second MCU core. +We leverage that boot mode to perform OTA firmware updates, including operations on a radio stack running on the second MCU core. # How does Flipper OTA work? @@ -22,16 +22,16 @@ For that, main firmware loads an updater image - a customized build of main Flip First, if there's a Radio stack image bundled with the update, updater compares its version with currently installed one. If they don't match, updater performs stack deinstallation followed by writing and installing a new one. The installation itself is performed by proprietary software, FUS, running on Core2, and leads to a series of system restarts. -Then updater validates and corrects Option Bytes — a special memory region containing low-level configuration for Flipper's MCU. +Then, updater validates and corrects Option Bytes — a special memory region containing low-level configuration for Flipper's MCU. After that, updater loads a `.dfu` file with firmware to be flashed, checks its integrity using CRC32, writes it to system flash and validates written data. ## 3. Restoring internal storage and updating resources -After performing operations on flash memory, system restarts into newly flashed firmware. Then it performs restoration of previously backed up `/int` contents. +After performing operations on flash memory, the system restarts into newly flashed firmware. Then it performs restoration of previously backed up `/int` contents. -If update package contains an additional resources archive, it is extracted onto SD card. +If the update package contains an additional resources archive, it is extracted onto SD card. # Update manifest @@ -40,13 +40,13 @@ Update packages come with a manifest that contains a description of its contents ## Mandatory fields -Update manifest must contain the following keys in given order: +An update manifest must contain the following keys in given order: * __Filetype__: a constant string, "Flipper firmware upgrade configuration"; * __Version__: manifest version. Current value is 2; -* __Info__: arbitraty string, describing package contents; +* __Info__: arbitrary string, describing package contents; * __Target__: hardware revision the package is built for; @@ -56,7 +56,7 @@ Update manifest must contain the following keys in given order: ## Optional fields -Other fields may have empty values, is such case updater skips all operations related to such values. +Other fields may have empty values, is such case, updater skips all operations related to such values. * __Radio__: file name of radio stack image, provided by STM; @@ -66,16 +66,16 @@ Other fields may have empty values, is such case updater skips all operations re * __Radio CRC__: CRC32 of radio image; -* __Resources__: file name of TAR acrhive with resources to be extracted on SD card; +* __Resources__: file name of TAR archive with resources to be extracted on SD card; * __OB reference__, __OB mask__, __OB write mask__: reference values for validating and correcting option bytes. # OTA update error codes -We designed the OTA update process to be as fail-safe as possible. We don't start any risky operation before validating all related pieces of data to ensure we don't leave the device in partially updated, or bricked, state. +We designed the OTA update process to be as fail-safe as possible. We don't start any risky operation before validating all related pieces of data to ensure we don't leave the device in a partially updated, or bricked, state. -Even if something goes wrong, Updater gives you an option to retry failed operations, and reports its state with an error code. These error codes have an `[XX-YY]` format, where `XX` encodes an operation that failed, and `YY` contains extra details on its progress where the error occured. +Even if something goes wrong, Updater gives you an option to retry failed operations, and reports its state with an error code. These error codes have an `[XX-YY]` format, where `XX` encodes an operation that failed, and `YY` contains extra details on its progress where the error occurred. | Stage description | Code | Progress | Description | |:-----------------------:|-------:|------------|--------------------------------------------| diff --git a/documentation/UniversalRemotes.md b/documentation/UniversalRemotes.md new file mode 100644 index 00000000..ac98d451 --- /dev/null +++ b/documentation/UniversalRemotes.md @@ -0,0 +1,36 @@ +# Universal Remotes +## Air Conditioners +### Recording signals +Air conditioners differ from most other infrared-controlled devices because their state is tracked by the remote. +The majority of A/C remotes have a small display which shows current mode, temperature and other settings. +When the user presses a button, a whole set of parameters is transmitted to the device, which must be recorded and used as a whole. + +In order to add a particular air conditioner to the universal remote, 6 signals must be recorded: `Off`, `Dh`, `Cool_hi`, `Cool_lo`, `Heat_hi`, `Heat_lo`. +Each signal (except `Off`) is recorded using the following algorithm: + +1. Get the remote and press the **Power Button** so that the display shows that A/C is ON. +2. Set the A/C to the corresponding mode (see table below), while leaving other parameters such as fan speed or vane on **AUTO** (if applicable). +3. Press the **POWER** button to switch the A/C off. +4. Start learning a new remote on Flipper if it's the first button or press `+` to add a new button otherwise. +5. Point the remote to Flipper's IR receiver as directed and press **POWER** button once again. +6. Save the resulting signal under the specified name. +7. Repeat the steps 2-6 for each signal from the table below. + +| Signal | Mode | Temperature | Note | +| :-----: | :--------: | :---------: | ----------------------------------- | +| Dh | Dehumidify | N/A | | +| Cool_hi | Cooling | See note | Lowest temperature in cooling mode | +| Cool_lo | Cooling | 23°C | | +| Heat_hi | Heating | See note | Highest temperature in heating mode | +| Heat_lo | Heating | 23°C | | + +Finally, record the `Off` signal: +1. Make sure the display shows that A/C is ON. +2. Start learning a new signal on Flipper and point the remote towards the IR receiver. +3. Press the **POWER** button so that the remote shows the OFF state. +4. Save the resulting signal under the name `Off`. + +The resulting remote file should now contain 6 signals. Any of them can be omitted, but that will mean that this functionality will not be used. +Test the file against the actual device. Every signal must do what it's supposed to. +If everything checks out, add these signals to the [A/C universal remote file](/assets/resources/infrared/assets/ac.ir) +and open a pull request. diff --git a/documentation/fbt.md b/documentation/fbt.md index 48726273..090ff78f 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -38,22 +38,23 @@ To run cleanup (think of `make clean`) for specified targets, add `-c` option. ## FBT targets -FBT keeps track of internal dependencies, so you only need to build the highest-level target you need, and FBT will make sure everything they depend on is up-to-date. +**`fbt`** keeps track of internal dependencies, so you only need to build the highest-level target you need, and **`fbt`** will make sure everything they depend on is up-to-date. ### High-level (what you most likely need) - `fw_dist` - build & publish firmware to `dist` folder. This is a default target, when no other are specified +- `plugin_dist` - build external plugins & publish to `dist` folder - `updater_package`, `updater_minpackage` - build self-update package. Minimal version only inclues firmware's DFU file; full version also includes radio stack & resources for SD card - `copro_dist` - bundle Core2 FUS+stack binaries for qFlipper - `flash` - flash attached device with OpenOCD over ST-Link - `flash_usb`, `flash_usb_full` - build, upload and install update package to device over USB. See details on `updater_package`, `updater_minpackage` - `debug` - build and flash firmware, then attach with gdb with firmware's .elf loaded -- `debug_other` - attach gdb without loading any .elf. Allows to manually add external elf files with `add-symbol-file` in gdb +- `debug_other`, `debug_other_blackmagic` - attach gdb without loading any .elf. Allows to manually add external elf files with `add-symbol-file` in gdb - `updater_debug` - attach gdb with updater's .elf loaded - `blackmagic` - debug firmware with Blackmagic probe (WiFi dev board) - `openocd` - just start OpenOCD - `get_blackmagic` - output blackmagic address in gdb remote format. Useful for IDE integration -- `lint`, `format` - run clang-tidy on C source code to check and reformat it according to `.clang-format` specs +- `lint`, `format` - run clang-format on C source code to check and reformat it according to `.clang-format` specs - `lint_py`, `format_py` - run [black](https://black.readthedocs.io/en/stable/index.html) on Python source code, build system files & application manifests ### Firmware targets @@ -82,7 +83,7 @@ FBT keeps track of internal dependencies, so you only need to build the highest- ## Command-line parameters - `--options optionfile.py` (default value `fbt_options.py`) - load file with multiple configuration values -- `--with-updater` - enables updater-related targets and dependency tracking. Enabling this option introduces extra startup time costs, so use it when bundling update packages. _Explicily enabling this should no longer be required, fbt now has specific handling for updater-related targets_ +- `--with-updater` - enables updater-related targets and dependency tracking. Enabling this option introduces extra startup time costs, so use it when bundling update packages. _Explicily enabling this should no longer be required, **`fbt`** now has specific handling for updater-related targets_ - `--extra-int-apps=app1,app2,appN` - forces listed apps to be built as internal with `firmware` target - `--extra-ext-apps=app1,app2,appN` - forces listed apps to be built as external with `firmware_extapps` target diff --git a/fbt_options.py b/fbt_options.py index b154d26a..716f99fd 100644 --- a/fbt_options.py +++ b/fbt_options.py @@ -66,22 +66,18 @@ LOADER_AUTOSTART = "" FIRMWARE_APPS = { "default": [ - "crypto_start", # Svc "basic_services", # Apps - "basic_apps", - "updater_app", - "storage_move_to_sd", - "archive", + "main_apps", + "system_apps", # Settings - "passport", - "system_settings", - "about", - # Plugins - "basic_plugins", + "settings_apps", + # Stock plugins - no longer built into fw, now they're .faps + # Yet you can still build them as a part of fw + # "basic_plugins", # Debug - "debug_apps", + # "debug_apps", ], "unit_tests": [ "basic_services", diff --git a/firmware.scons b/firmware.scons index f47e9ff2..530634ef 100644 --- a/firmware.scons +++ b/firmware.scons @@ -1,6 +1,6 @@ Import("ENV", "fw_build_meta") -import os +import itertools from fbt.util import ( should_gen_cdb_and_link_dir, @@ -13,6 +13,7 @@ env = ENV.Clone( ("compilation_db", {"COMPILATIONDB_COMSTR": "\tCDB\t${TARGET}"}), "fwbin", "fbt_apps", + "fbt_sdk", ], COMPILATIONDB_USE_ABSPATH=False, BUILD_DIR=fw_build_meta["build_dir"], @@ -28,7 +29,7 @@ env = ENV.Clone( ], CPPPATH=[ "#/furi", - "#/applications", + *(f"#/{app_dir[0]}" for app_dir in ENV["APPDIRS"] if app_dir[1]), "#/firmware/targets/f${TARGET_HW}/ble_glue", "#/firmware/targets/f${TARGET_HW}/fatfs", "#/firmware/targets/f${TARGET_HW}/furi_hal", @@ -58,6 +59,15 @@ env = ENV.Clone( "FURI_DEBUG" if ENV["DEBUG"] else "FURI_NDEBUG", ], }, + "flipper_application": { + "CCFLAGS": [ + "-Og", + ], + "CPPDEFINES": [ + "NDEBUG", + "FURI_DEBUG" if ENV["DEBUG"] else "FURI_NDEBUG", + ], + }, }, ) @@ -80,6 +90,12 @@ if not env["VERBOSE"]: HEXCOMSTR="\tHEX\t${TARGET}", BINCOMSTR="\tBIN\t${TARGET}", DFUCOMSTR="\tDFU\t${TARGET}", + SDK_PREGEN_COMSTR="\tPREGEN\t${TARGET}", + SDK_COMSTR="\tSDKSRC\t${TARGET}", + SDKSYM_UPDATER_COMSTR="\tSDKCHK\t${TARGET}", + SDKSYM_GENERATOR_COMSTR="\tSDKSYM\t${TARGET}", + APPMETA_COMSTR="\tAPPMETA\t${TARGET}", + APPMETAEMBED_COMSTR="\tFAP\t${TARGET}", ) @@ -127,11 +143,13 @@ fwenv.LoadApplicationManifests() fwenv.PrepareApplicationsBuild() # Build external apps -extapps = SConscript("applications/extapps.scons", exports={"ENV": fwenv}) +extapps = fwenv["FW_EXTAPPS"] = SConscript( + "site_scons/extapps.scons", exports={"ENV": fwenv} +) # Add preprocessor definitions for current set of apps -fwenv.AppendUnique( +fwenv.Append( CPPDEFINES=fwenv["APPBUILD"].get_apps_cdefs(), ) @@ -141,23 +159,26 @@ apps_c = fwenv.ApplicationsC( "applications/applications.c", [Value(fwenv["APPS"]), Value(fwenv["LOADER_AUTOSTART"])], ) + # Adding dependency on manifest files so apps.c is rebuilt when any manifest is changed -fwenv.Depends(apps_c, fwenv.GlobRecursive("*.fam", "#/applications")) +for app_dir, _ in env["APPDIRS"]: + app_dir_node = env.Dir("#").Dir(app_dir) + fwenv.Depends(apps_c, fwenv.GlobRecursive("*.fam", app_dir_node)) sources = [apps_c] # Gather sources only from app folders in current configuration -for app_folder in fwenv["APPBUILD"].get_builtin_app_folders(): - sources += fwenv.GlobRecursive("*.c*", os.path.join("applications", app_folder)) +sources.extend( + itertools.chain.from_iterable( + fwenv.GlobRecursive(source_type, appdir.relpath) + for appdir, source_type in fwenv["APPBUILD"].get_builtin_app_folders() + ) +) fwenv.AppendUnique( LINKFLAGS=[ "-specs=nano.specs", "-specs=nosys.specs", - "-Wl,--start-group", - "-lstdc++", - "-lsupc++", - "-Wl,--end-group", "-Wl,--gc-sections", "-Wl,--undefined=uxTopUsedPriority", "-Wl,--wrap,_malloc_r", @@ -174,7 +195,6 @@ fwenv.AppendUnique( # print(fwenv.Dump()) # Full firmware definition - fwelf = fwenv["FW_ELF"] = fwenv.Program( "${FIRMWARE_BUILD_CFG}", sources, @@ -199,8 +219,8 @@ fwelf = fwenv["FW_ELF"] = fwenv.Program( "assets", "misc", "mbedtls", - "loclass", "lfrfid", + "flipper_application", # 2nd round "flipperformat", "toolbox", @@ -248,6 +268,8 @@ if should_gen_cdb_and_link_dir(fwenv, BUILD_TARGETS): Precious(fwcdb) NoClean(fwcdb) Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_cdb", fwcdb) + AlwaysBuild(fwenv["FIRMWARE_BUILD_CFG"] + "_cdb", fwcdb) + Alias(fwcdb, "") fw_artifacts.append(fwcdb) # Adding as a phony target, so folder link is updated even if elf didn't change @@ -263,5 +285,42 @@ if should_gen_cdb_and_link_dir(fwenv, BUILD_TARGETS): Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_all", fw_artifacts) +if fwenv["IS_BASE_FIRMWARE"]: + sdk_source = fwenv.SDKPrebuilder( + "sdk_origin", + [], + # Filtering out things cxxheaderparser cannot handle + SDK_PP_FLAGS=[ + '-D"_Static_assert(x,y)="', + '-D"__asm__(x)="', + '-D"__attribute__(x)="', + "-Drestrict=", + "-D_Noreturn=", + "-D__restrict=", + "-D__extension__=", + "-D__inline=inline", + "-D__inline__=inline", + ], + ) + Depends(sdk_source, (fwenv["SDK_HEADERS"], fwenv["FW_ASSETS_HEADERS"])) + + sdk_tree = fwenv.SDKTree("sdk/sdk.opts", "sdk_origin") + AlwaysBuild(sdk_tree) + Alias("sdk_tree", sdk_tree) + + sdk_apicheck = fwenv.SDKSymUpdater(fwenv.subst("$SDK_DEFINITION"), "sdk_origin") + Precious(sdk_apicheck) + NoClean(sdk_apicheck) + AlwaysBuild(sdk_apicheck) + Alias("sdk_check", sdk_apicheck) + + sdk_apisyms = fwenv.SDKSymGenerator( + "assets/compiled/symbols.h", fwenv.subst("$SDK_DEFINITION") + ) + Alias("api_syms", sdk_apisyms) + + if fwenv["FORCE"]: + fwenv.AlwaysBuild(sdk_source, sdk_tree, sdk_apicheck, sdk_apisyms) + Return("fwenv") diff --git a/firmware/SConscript b/firmware/SConscript index 3530ed82..5795e242 100644 --- a/firmware/SConscript +++ b/firmware/SConscript @@ -1,6 +1,16 @@ Import("env") -env.Append(LINT_SOURCES=["firmware"]) +env.Append( + LINT_SOURCES=["firmware"], + # SDK_HEADERS=[env.File("#/firmware/targets/furi_hal_include/furi_hal.h")], + SDK_HEADERS=[ + *env.GlobRecursive("*.h", "#/firmware/targets/furi_hal_include", "*_i.h"), + *env.GlobRecursive("*.h", "#/firmware/targets/f${TARGET_HW}/furi_hal", "*_i.h"), + File("#/firmware/targets/f7/platform_specific/intrinsic_export.h"), + ], +) +env.SetDefault(SDK_DEFINITION=env.File("./targets/f${TARGET_HW}/api_symbols.csv")) + libenv = env.Clone(FW_LIB_NAME="flipper${TARGET_HW}") libenv.Append( diff --git a/firmware/targets/f7/Inc/FreeRTOSConfig.h b/firmware/targets/f7/Inc/FreeRTOSConfig.h index ab2dc14e..69ef9406 100644 --- a/firmware/targets/f7/Inc/FreeRTOSConfig.h +++ b/firmware/targets/f7/Inc/FreeRTOSConfig.h @@ -76,19 +76,8 @@ to exclude the API function. */ #define INCLUDE_xTaskGetSchedulerState 1 #define INCLUDE_xTimerPendFunctionCall 1 -/* CMSIS-RTOS V2 flags */ -#define configUSE_OS2_THREAD_SUSPEND_RESUME 1 -#define configUSE_OS2_THREAD_ENUMERATE 1 -#define configUSE_OS2_THREAD_FLAGS 1 -#define configUSE_OS2_TIMER 1 -#define configUSE_OS2_MUTEX 1 - -// NEVER TO BE USED, because of their hard realtime nature -// #define configUSE_OS2_EVENTFLAGS_FROM_ISR 1 - -/* CMSIS-RTOS */ +/* Furi-specific */ #define configTASK_NOTIFICATION_ARRAY_ENTRIES 2 -#define CMSIS_TASK_NOTIFY_INDEX 1 extern __attribute__((__noreturn__)) void furi_thread_catch(); #define configTASK_RETURN_ADDRESS (furi_thread_catch + 2) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv new file mode 100644 index 00000000..ac4df046 --- /dev/null +++ b/firmware/targets/f7/api_symbols.csv @@ -0,0 +1,2987 @@ +entry,status,name,type,params +Version,+,1.9,, +Header,+,applications/services/bt/bt_service/bt.h,, +Header,+,applications/services/cli/cli.h,, +Header,+,applications/services/cli/cli_vcp.h,, +Header,+,applications/services/dialogs/dialogs.h,, +Header,+,applications/services/dolphin/dolphin.h,, +Header,+,applications/services/gui/elements.h,, +Header,+,applications/services/gui/gui.h,, +Header,+,applications/services/gui/modules/button_menu.h,, +Header,+,applications/services/gui/modules/button_panel.h,, +Header,+,applications/services/gui/modules/byte_input.h,, +Header,+,applications/services/gui/modules/dialog_ex.h,, +Header,+,applications/services/gui/modules/empty_screen.h,, +Header,+,applications/services/gui/modules/file_browser.h,, +Header,+,applications/services/gui/modules/file_browser_worker.h,, +Header,+,applications/services/gui/modules/loading.h,, +Header,+,applications/services/gui/modules/menu.h,, +Header,+,applications/services/gui/modules/popup.h,, +Header,+,applications/services/gui/modules/submenu.h,, +Header,+,applications/services/gui/modules/text_box.h,, +Header,+,applications/services/gui/modules/text_input.h,, +Header,+,applications/services/gui/modules/validators.h,, +Header,+,applications/services/gui/modules/variable_item_list.h,, +Header,+,applications/services/gui/modules/widget.h,, +Header,+,applications/services/gui/modules/widget_elements/widget_element.h,, +Header,+,applications/services/gui/view_dispatcher.h,, +Header,+,applications/services/gui/view_stack.h,, +Header,+,applications/services/input/input.h,, +Header,+,applications/services/loader/loader.h,, +Header,+,applications/services/notification/notification.h,, +Header,+,applications/services/notification/notification_messages.h,, +Header,+,applications/services/power/power_service/power.h,, +Header,+,applications/services/rpc/rpc_app.h,, +Header,+,applications/services/storage/storage.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_clock.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_console.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_flash.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_gpio.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_i2c_config.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_i2c_types.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_idle_timer.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_interrupt.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_os.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_resources.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_spi_config.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_spi_types.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_subghz_configs.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_uart.h,, +Header,+,firmware/targets/f7/furi_hal/furi_hal_usb_cdc.h,, +Header,+,firmware/targets/f7/platform_specific/intrinsic_export.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_bt.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_bt_hid.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_bt_serial.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_compress.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_cortex.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_crypto.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_debug.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_i2c.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_ibutton.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_info.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_infrared.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_light.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_memory.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_mpu.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_nfc.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_power.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_random.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_region.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_rfid.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_rtc.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_sd.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_speaker.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_spi.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_subghz.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_usb.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,, +Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_adc.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_bus.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_comp.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_cortex.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_crc.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_crs.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_dma.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_dmamux.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_exti.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_gpio.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_hsem.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_i2c.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_ipcc.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_iwdg.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_lptim.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_lpuart.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_pka.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_pwr.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_rcc.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_rng.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_rtc.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_spi.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_system.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_tim.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_usart.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_utils.h,, +Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_wwdg.h,, +Header,+,lib/flipper_application/flipper_application.h,, +Header,+,lib/flipper_format/flipper_format.h,, +Header,+,lib/flipper_format/flipper_format_i.h,, +Header,+,lib/lfrfid/lfrfid_dict_file.h,, +Header,+,lib/lfrfid/lfrfid_raw_file.h,, +Header,+,lib/lfrfid/lfrfid_raw_worker.h,, +Header,+,lib/lfrfid/lfrfid_worker.h,, +Header,+,lib/lfrfid/protocols/lfrfid_protocols.h,, +Header,+,lib/lfrfid/tools/bit_lib.h,, +Header,+,lib/micro-ecc/uECC.h,, +Header,+,lib/one_wire/ibutton/ibutton_worker.h,, +Header,+,lib/one_wire/maxim_crc.h,, +Header,+,lib/one_wire/one_wire_device.h,, +Header,+,lib/one_wire/one_wire_host.h,, +Header,+,lib/one_wire/one_wire_host_timing.h,, +Header,+,lib/one_wire/one_wire_slave.h,, +Header,+,lib/print/wrappers.h,, +Header,+,lib/subghz/environment.h,, +Header,+,lib/subghz/protocols/raw.h,, +Header,+,lib/subghz/receiver.h,, +Header,+,lib/subghz/subghz_tx_rx_worker.h,, +Header,+,lib/subghz/subghz_worker.h,, +Header,+,lib/subghz/transmitter.h,, +Header,+,lib/toolbox/args.h,, +Header,+,lib/toolbox/crc32_calc.h,, +Header,+,lib/toolbox/dir_walk.h,, +Header,+,lib/toolbox/hmac_sha256.h,, +Header,+,lib/toolbox/manchester_decoder.h,, +Header,+,lib/toolbox/manchester_encoder.h,, +Header,+,lib/toolbox/md5.h,, +Header,+,lib/toolbox/path.h,, +Header,+,lib/toolbox/protocols/protocol_dict.h,, +Header,+,lib/toolbox/random_name.h,, +Header,+,lib/toolbox/saved_struct.h,, +Header,+,lib/toolbox/stream/buffered_file_stream.h,, +Header,+,lib/toolbox/stream/file_stream.h,, +Header,+,lib/toolbox/stream/stream.h,, +Header,+,lib/toolbox/stream/string_stream.h,, +Header,+,lib/toolbox/tar/tar_archive.h,, +Header,+,lib/toolbox/version.h,, +Function,-,LL_ADC_CommonDeInit,ErrorStatus,ADC_Common_TypeDef* +Function,-,LL_ADC_CommonInit,ErrorStatus,"ADC_Common_TypeDef*, LL_ADC_CommonInitTypeDef*" +Function,-,LL_ADC_CommonStructInit,void,LL_ADC_CommonInitTypeDef* +Function,-,LL_ADC_DeInit,ErrorStatus,ADC_TypeDef* +Function,-,LL_ADC_INJ_Init,ErrorStatus,"ADC_TypeDef*, LL_ADC_INJ_InitTypeDef*" +Function,-,LL_ADC_INJ_StructInit,void,LL_ADC_INJ_InitTypeDef* +Function,-,LL_ADC_Init,ErrorStatus,"ADC_TypeDef*, LL_ADC_InitTypeDef*" +Function,-,LL_ADC_REG_Init,ErrorStatus,"ADC_TypeDef*, LL_ADC_REG_InitTypeDef*" +Function,-,LL_ADC_REG_StructInit,void,LL_ADC_REG_InitTypeDef* +Function,-,LL_ADC_StructInit,void,LL_ADC_InitTypeDef* +Function,-,LL_COMP_DeInit,ErrorStatus,COMP_TypeDef* +Function,+,LL_COMP_Init,ErrorStatus,"COMP_TypeDef*, LL_COMP_InitTypeDef*" +Function,-,LL_COMP_StructInit,void,LL_COMP_InitTypeDef* +Function,-,LL_CRC_DeInit,ErrorStatus,CRC_TypeDef* +Function,-,LL_CRS_DeInit,ErrorStatus, +Function,+,LL_DMA_DeInit,ErrorStatus,"DMA_TypeDef*, uint32_t" +Function,+,LL_DMA_Init,ErrorStatus,"DMA_TypeDef*, uint32_t, LL_DMA_InitTypeDef*" +Function,-,LL_DMA_StructInit,void,LL_DMA_InitTypeDef* +Function,-,LL_EXTI_DeInit,ErrorStatus, +Function,-,LL_EXTI_Init,ErrorStatus,LL_EXTI_InitTypeDef* +Function,-,LL_EXTI_StructInit,void,LL_EXTI_InitTypeDef* +Function,-,LL_GPIO_DeInit,ErrorStatus,GPIO_TypeDef* +Function,+,LL_GPIO_Init,ErrorStatus,"GPIO_TypeDef*, LL_GPIO_InitTypeDef*" +Function,-,LL_GPIO_StructInit,void,LL_GPIO_InitTypeDef* +Function,-,LL_I2C_DeInit,ErrorStatus,I2C_TypeDef* +Function,+,LL_I2C_Init,ErrorStatus,"I2C_TypeDef*, LL_I2C_InitTypeDef*" +Function,-,LL_I2C_StructInit,void,LL_I2C_InitTypeDef* +Function,-,LL_Init1msTick,void,uint32_t +Function,+,LL_LPTIM_DeInit,ErrorStatus,LPTIM_TypeDef* +Function,-,LL_LPTIM_Disable,void,LPTIM_TypeDef* +Function,+,LL_LPTIM_Init,ErrorStatus,"LPTIM_TypeDef*, LL_LPTIM_InitTypeDef*" +Function,-,LL_LPTIM_StructInit,void,LL_LPTIM_InitTypeDef* +Function,-,LL_LPUART_DeInit,ErrorStatus,USART_TypeDef* +Function,+,LL_LPUART_Init,ErrorStatus,"USART_TypeDef*, LL_LPUART_InitTypeDef*" +Function,-,LL_LPUART_StructInit,void,LL_LPUART_InitTypeDef* +Function,-,LL_PKA_DeInit,ErrorStatus,PKA_TypeDef* +Function,-,LL_PKA_Init,ErrorStatus,"PKA_TypeDef*, LL_PKA_InitTypeDef*" +Function,-,LL_PKA_StructInit,void,LL_PKA_InitTypeDef* +Function,-,LL_PLL_ConfigSystemClock_HSE,ErrorStatus,"uint32_t, LL_UTILS_PLLInitTypeDef*, LL_UTILS_ClkInitTypeDef*" +Function,-,LL_PLL_ConfigSystemClock_HSI,ErrorStatus,"LL_UTILS_PLLInitTypeDef*, LL_UTILS_ClkInitTypeDef*" +Function,-,LL_PLL_ConfigSystemClock_MSI,ErrorStatus,"LL_UTILS_PLLInitTypeDef*, LL_UTILS_ClkInitTypeDef*" +Function,-,LL_PWR_DeInit,ErrorStatus, +Function,-,LL_RCC_DeInit,ErrorStatus, +Function,-,LL_RCC_GetADCClockFreq,uint32_t,uint32_t +Function,-,LL_RCC_GetCLK48ClockFreq,uint32_t,uint32_t +Function,-,LL_RCC_GetI2CClockFreq,uint32_t,uint32_t +Function,-,LL_RCC_GetLPTIMClockFreq,uint32_t,uint32_t +Function,+,LL_RCC_GetLPUARTClockFreq,uint32_t,uint32_t +Function,-,LL_RCC_GetRFWKPClockFreq,uint32_t, +Function,-,LL_RCC_GetRNGClockFreq,uint32_t,uint32_t +Function,-,LL_RCC_GetRTCClockFreq,uint32_t, +Function,-,LL_RCC_GetSAIClockFreq,uint32_t,uint32_t +Function,-,LL_RCC_GetSMPSClockFreq,uint32_t, +Function,-,LL_RCC_GetSystemClocksFreq,void,LL_RCC_ClocksTypeDef* +Function,+,LL_RCC_GetUSARTClockFreq,uint32_t,uint32_t +Function,-,LL_RCC_GetUSBClockFreq,uint32_t,uint32_t +Function,-,LL_RNG_DeInit,ErrorStatus,RNG_TypeDef* +Function,-,LL_RNG_Init,ErrorStatus,"RNG_TypeDef*, LL_RNG_InitTypeDef*" +Function,-,LL_RNG_StructInit,void,LL_RNG_InitTypeDef* +Function,-,LL_RTC_ALMA_Init,ErrorStatus,"RTC_TypeDef*, uint32_t, LL_RTC_AlarmTypeDef*" +Function,-,LL_RTC_ALMA_StructInit,void,LL_RTC_AlarmTypeDef* +Function,-,LL_RTC_ALMB_Init,ErrorStatus,"RTC_TypeDef*, uint32_t, LL_RTC_AlarmTypeDef*" +Function,-,LL_RTC_ALMB_StructInit,void,LL_RTC_AlarmTypeDef* +Function,-,LL_RTC_DATE_Init,ErrorStatus,"RTC_TypeDef*, uint32_t, LL_RTC_DateTypeDef*" +Function,-,LL_RTC_DATE_StructInit,void,LL_RTC_DateTypeDef* +Function,-,LL_RTC_DeInit,ErrorStatus,RTC_TypeDef* +Function,+,LL_RTC_EnterInitMode,ErrorStatus,RTC_TypeDef* +Function,-,LL_RTC_ExitInitMode,ErrorStatus,RTC_TypeDef* +Function,+,LL_RTC_Init,ErrorStatus,"RTC_TypeDef*, LL_RTC_InitTypeDef*" +Function,-,LL_RTC_StructInit,void,LL_RTC_InitTypeDef* +Function,-,LL_RTC_TIME_Init,ErrorStatus,"RTC_TypeDef*, uint32_t, LL_RTC_TimeTypeDef*" +Function,-,LL_RTC_TIME_StructInit,void,LL_RTC_TimeTypeDef* +Function,-,LL_RTC_WaitForSynchro,ErrorStatus,RTC_TypeDef* +Function,-,LL_SPI_DeInit,ErrorStatus,SPI_TypeDef* +Function,+,LL_SPI_Init,ErrorStatus,"SPI_TypeDef*, LL_SPI_InitTypeDef*" +Function,-,LL_SPI_StructInit,void,LL_SPI_InitTypeDef* +Function,-,LL_SetFlashLatency,ErrorStatus,uint32_t +Function,+,LL_SetSystemCoreClock,void,uint32_t +Function,-,LL_TIM_BDTR_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_BDTR_InitTypeDef*" +Function,-,LL_TIM_BDTR_StructInit,void,LL_TIM_BDTR_InitTypeDef* +Function,+,LL_TIM_DeInit,ErrorStatus,TIM_TypeDef* +Function,-,LL_TIM_ENCODER_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_ENCODER_InitTypeDef*" +Function,-,LL_TIM_ENCODER_StructInit,void,LL_TIM_ENCODER_InitTypeDef* +Function,-,LL_TIM_HALLSENSOR_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_HALLSENSOR_InitTypeDef*" +Function,-,LL_TIM_HALLSENSOR_StructInit,void,LL_TIM_HALLSENSOR_InitTypeDef* +Function,-,LL_TIM_IC_Init,ErrorStatus,"TIM_TypeDef*, uint32_t, LL_TIM_IC_InitTypeDef*" +Function,-,LL_TIM_IC_StructInit,void,LL_TIM_IC_InitTypeDef* +Function,+,LL_TIM_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_InitTypeDef*" +Function,+,LL_TIM_OC_Init,ErrorStatus,"TIM_TypeDef*, uint32_t, LL_TIM_OC_InitTypeDef*" +Function,-,LL_TIM_OC_StructInit,void,LL_TIM_OC_InitTypeDef* +Function,-,LL_TIM_StructInit,void,LL_TIM_InitTypeDef* +Function,-,LL_USART_ClockInit,ErrorStatus,"USART_TypeDef*, LL_USART_ClockInitTypeDef*" +Function,-,LL_USART_ClockStructInit,void,LL_USART_ClockInitTypeDef* +Function,-,LL_USART_DeInit,ErrorStatus,USART_TypeDef* +Function,+,LL_USART_Init,ErrorStatus,"USART_TypeDef*, LL_USART_InitTypeDef*" +Function,-,LL_USART_StructInit,void,LL_USART_InitTypeDef* +Function,-,LL_mDelay,void,uint32_t +Function,-,SystemCoreClockUpdate,void, +Function,-,SystemInit,void, +Function,-,_Exit,void,int +Function,-,__assert,void,"const char*, int, const char*" +Function,+,__assert_func,void,"const char*, int, const char*, const char*" +Function,+,__clear_cache,void,"void*, void*" +Function,-,__eprintf,void,"const char*, const char*, unsigned int, const char*" +Function,+,__errno,int*, +Function,-,__fpclassifyd,int,double +Function,-,__fpclassifyf,int,float +Function,-,__getdelim,ssize_t,"char**, size_t*, int, FILE*" +Function,-,__getline,ssize_t,"char**, size_t*, FILE*" +Function,-,__isinfd,int,double +Function,-,__isinff,int,float +Function,-,__isnand,int,double +Function,-,__isnanf,int,float +Function,-,__itoa,char*,"int, char*, int" +Function,-,__locale_mb_cur_max,int, +Function,+,__retarget_lock_acquire,void,_LOCK_T +Function,+,__retarget_lock_acquire_recursive,void,_LOCK_T +Function,-,__retarget_lock_close,void,_LOCK_T +Function,+,__retarget_lock_close_recursive,void,_LOCK_T +Function,-,__retarget_lock_init,void,_LOCK_T* +Function,+,__retarget_lock_init_recursive,void,_LOCK_T* +Function,+,__retarget_lock_release,void,_LOCK_T +Function,+,__retarget_lock_release_recursive,void,_LOCK_T +Function,-,__retarget_lock_try_acquire,int,_LOCK_T +Function,-,__retarget_lock_try_acquire_recursive,int,_LOCK_T +Function,-,__signbitd,int,double +Function,-,__signbitf,int,float +Function,-,__signgam,int*, +Function,-,__srget_r,int,"_reent*, FILE*" +Function,-,__swbuf_r,int,"_reent*, int, FILE*" +Function,-,__utoa,char*,"unsigned, char*, int" +Function,+,__wrap___assert,void,"const char*, int, const char*" +Function,+,__wrap___assert_func,void,"const char*, int, const char*, const char*" +Function,+,__wrap_fflush,int,FILE* +Function,+,__wrap_printf,int,"const char*, ..." +Function,+,__wrap_putc,int,"int, FILE*" +Function,+,__wrap_putchar,int,int +Function,+,__wrap_puts,int,const char* +Function,+,__wrap_snprintf,int,"char*, size_t, const char*, ..." +Function,+,__wrap_vsnprintf,int,"char*, size_t, const char*, va_list" +Function,-,_asiprintf_r,int,"_reent*, char**, const char*, ..." +Function,-,_asniprintf_r,char*,"_reent*, char*, size_t*, const char*, ..." +Function,-,_asnprintf_r,char*,"_reent*, char*, size_t*, const char*, ..." +Function,-,_asprintf_r,int,"_reent*, char**, const char*, ..." +Function,-,_atoi_r,int,"_reent*, const char*" +Function,-,_atol_r,long,"_reent*, const char*" +Function,-,_atoll_r,long long,"_reent*, const char*" +Function,-,_calloc_r,void*,"_reent*, size_t, size_t" +Function,-,_diprintf_r,int,"_reent*, int, const char*, ..." +Function,-,_dprintf_r,int,"_reent*, int, const char*, ..." +Function,-,_drand48_r,double,_reent* +Function,-,_dtoa_r,char*,"_reent*, double, int, int, int*, int*, char**" +Function,-,_erand48_r,double,"_reent*, unsigned short[3]" +Function,-,_fclose_r,int,"_reent*, FILE*" +Function,-,_fcloseall_r,int,_reent* +Function,-,_fdopen_r,FILE*,"_reent*, int, const char*" +Function,-,_fflush_r,int,"_reent*, FILE*" +Function,-,_fgetc_r,int,"_reent*, FILE*" +Function,-,_fgetc_unlocked_r,int,"_reent*, FILE*" +Function,-,_fgetpos_r,int,"_reent*, FILE*, fpos_t*" +Function,-,_fgets_r,char*,"_reent*, char*, int, FILE*" +Function,-,_fgets_unlocked_r,char*,"_reent*, char*, int, FILE*" +Function,-,_findenv,char*,"const char*, int*" +Function,-,_findenv_r,char*,"_reent*, const char*, int*" +Function,-,_fiprintf_r,int,"_reent*, FILE*, const char*, ..." +Function,-,_fiscanf_r,int,"_reent*, FILE*, const char*, ..." +Function,-,_fmemopen_r,FILE*,"_reent*, void*, size_t, const char*" +Function,-,_fopen_r,FILE*,"_reent*, const char*, const char*" +Function,-,_fopencookie_r,FILE*,"_reent*, void*, const char*, cookie_io_functions_t" +Function,-,_fprintf_r,int,"_reent*, FILE*, const char*, ..." +Function,-,_fpurge_r,int,"_reent*, FILE*" +Function,-,_fputc_r,int,"_reent*, int, FILE*" +Function,-,_fputc_unlocked_r,int,"_reent*, int, FILE*" +Function,-,_fputs_r,int,"_reent*, const char*, FILE*" +Function,-,_fputs_unlocked_r,int,"_reent*, const char*, FILE*" +Function,-,_fread_r,size_t,"_reent*, void*, size_t, size_t, FILE*" +Function,-,_fread_unlocked_r,size_t,"_reent*, void*, size_t, size_t, FILE*" +Function,-,_free_r,void,"_reent*, void*" +Function,-,_freopen_r,FILE*,"_reent*, const char*, const char*, FILE*" +Function,-,_fscanf_r,int,"_reent*, FILE*, const char*, ..." +Function,-,_fseek_r,int,"_reent*, FILE*, long, int" +Function,-,_fseeko_r,int,"_reent*, FILE*, _off_t, int" +Function,-,_fsetpos_r,int,"_reent*, FILE*, const fpos_t*" +Function,-,_ftell_r,long,"_reent*, FILE*" +Function,-,_ftello_r,_off_t,"_reent*, FILE*" +Function,-,_funopen_r,FILE*,"_reent*, const void*, int (*)(void*, char*, int), int (*)(void*, const char*, int), fpos_t (*)(void*, fpos_t, int), int (*)(void*)" +Function,-,_fwrite_r,size_t,"_reent*, const void*, size_t, size_t, FILE*" +Function,-,_fwrite_unlocked_r,size_t,"_reent*, const void*, size_t, size_t, FILE*" +Function,-,_getc_r,int,"_reent*, FILE*" +Function,-,_getc_unlocked_r,int,"_reent*, FILE*" +Function,-,_getchar_r,int,_reent* +Function,-,_getchar_unlocked_r,int,_reent* +Function,-,_getenv_r,char*,"_reent*, const char*" +Function,-,_gets_r,char*,"_reent*, char*" +Function,-,_iprintf_r,int,"_reent*, const char*, ..." +Function,-,_iscanf_r,int,"_reent*, const char*, ..." +Function,-,_jrand48_r,long,"_reent*, unsigned short[3]" +Function,-,_l64a_r,char*,"_reent*, long" +Function,-,_lcong48_r,void,"_reent*, unsigned short[7]" +Function,-,_lrand48_r,long,_reent* +Function,-,_malloc_r,void*,"_reent*, size_t" +Function,-,_mblen_r,int,"_reent*, const char*, size_t, _mbstate_t*" +Function,-,_mbstowcs_r,size_t,"_reent*, wchar_t*, const char*, size_t, _mbstate_t*" +Function,-,_mbtowc_r,int,"_reent*, wchar_t*, const char*, size_t, _mbstate_t*" +Function,-,_mkdtemp_r,char*,"_reent*, char*" +Function,-,_mkostemp_r,int,"_reent*, char*, int" +Function,-,_mkostemps_r,int,"_reent*, char*, int, int" +Function,-,_mkstemp_r,int,"_reent*, char*" +Function,-,_mkstemps_r,int,"_reent*, char*, int" +Function,-,_mktemp_r,char*,"_reent*, char*" +Function,-,_mrand48_r,long,_reent* +Function,-,_mstats_r,void,"_reent*, char*" +Function,-,_nrand48_r,long,"_reent*, unsigned short[3]" +Function,-,_open_memstream_r,FILE*,"_reent*, char**, size_t*" +Function,-,_perror_r,void,"_reent*, const char*" +Function,-,_printf_r,int,"_reent*, const char*, ..." +Function,-,_putc_r,int,"_reent*, int, FILE*" +Function,-,_putc_unlocked_r,int,"_reent*, int, FILE*" +Function,-,_putchar,void,char +Function,-,_putchar_r,int,"_reent*, int" +Function,-,_putchar_unlocked_r,int,"_reent*, int" +Function,-,_putenv_r,int,"_reent*, char*" +Function,-,_puts_r,int,"_reent*, const char*" +Function,-,_realloc_r,void*,"_reent*, void*, size_t" +Function,-,_reallocf_r,void*,"_reent*, void*, size_t" +Function,-,_reclaim_reent,void,_reent* +Function,-,_remove_r,int,"_reent*, const char*" +Function,-,_rename_r,int,"_reent*, const char*, const char*" +Function,-,_rewind_r,void,"_reent*, FILE*" +Function,-,_scanf_r,int,"_reent*, const char*, ..." +Function,-,_seed48_r,unsigned short*,"_reent*, unsigned short[3]" +Function,-,_setenv_r,int,"_reent*, const char*, const char*, int" +Function,-,_siprintf_r,int,"_reent*, char*, const char*, ..." +Function,-,_siscanf_r,int,"_reent*, const char*, const char*, ..." +Function,-,_sniprintf_r,int,"_reent*, char*, size_t, const char*, ..." +Function,-,_snprintf_r,int,"_reent*, char*, size_t, const char*, ..." +Function,-,_sprintf_r,int,"_reent*, char*, const char*, ..." +Function,-,_srand48_r,void,"_reent*, long" +Function,-,_sscanf_r,int,"_reent*, const char*, const char*, ..." +Function,-,_strdup_r,char*,"_reent*, const char*" +Function,-,_strerror_r,char*,"_reent*, int, int, int*" +Function,-,_strndup_r,char*,"_reent*, const char*, size_t" +Function,-,_strtod_r,double,"_reent*, const char*, char**" +Function,-,_strtol_r,long,"_reent*, const char*, char**, int" +Function,-,_strtold_r,long double,"_reent*, const char*, char**" +Function,-,_strtoll_r,long long,"_reent*, const char*, char**, int" +Function,-,_strtoul_r,unsigned long,"_reent*, const char*, char**, int" +Function,-,_strtoull_r,unsigned long long,"_reent*, const char*, char**, int" +Function,-,_system_r,int,"_reent*, const char*" +Function,-,_tempnam_r,char*,"_reent*, const char*, const char*" +Function,-,_tmpfile_r,FILE*,_reent* +Function,-,_tmpnam_r,char*,"_reent*, char*" +Function,-,_ungetc_r,int,"_reent*, int, FILE*" +Function,-,_unsetenv_r,int,"_reent*, const char*" +Function,-,_vasiprintf_r,int,"_reent*, char**, const char*, __gnuc_va_list" +Function,-,_vasniprintf_r,char*,"_reent*, char*, size_t*, const char*, __gnuc_va_list" +Function,-,_vasnprintf_r,char*,"_reent*, char*, size_t*, const char*, __gnuc_va_list" +Function,-,_vasprintf_r,int,"_reent*, char**, const char*, __gnuc_va_list" +Function,-,_vdiprintf_r,int,"_reent*, int, const char*, __gnuc_va_list" +Function,-,_vdprintf_r,int,"_reent*, int, const char*, __gnuc_va_list" +Function,-,_vfiprintf_r,int,"_reent*, FILE*, const char*, __gnuc_va_list" +Function,-,_vfiscanf_r,int,"_reent*, FILE*, const char*, __gnuc_va_list" +Function,-,_vfprintf_r,int,"_reent*, FILE*, const char*, __gnuc_va_list" +Function,-,_vfscanf_r,int,"_reent*, FILE*, const char*, __gnuc_va_list" +Function,-,_viprintf_r,int,"_reent*, const char*, __gnuc_va_list" +Function,-,_viscanf_r,int,"_reent*, const char*, __gnuc_va_list" +Function,-,_vprintf_r,int,"_reent*, const char*, __gnuc_va_list" +Function,-,_vscanf_r,int,"_reent*, const char*, __gnuc_va_list" +Function,-,_vsiprintf_r,int,"_reent*, char*, const char*, __gnuc_va_list" +Function,-,_vsiscanf_r,int,"_reent*, const char*, const char*, __gnuc_va_list" +Function,-,_vsniprintf_r,int,"_reent*, char*, size_t, const char*, __gnuc_va_list" +Function,-,_vsnprintf_r,int,"_reent*, char*, size_t, const char*, __gnuc_va_list" +Function,-,_vsprintf_r,int,"_reent*, char*, const char*, __gnuc_va_list" +Function,-,_vsscanf_r,int,"_reent*, const char*, const char*, __gnuc_va_list" +Function,-,_wcstombs_r,size_t,"_reent*, char*, const wchar_t*, size_t, _mbstate_t*" +Function,-,_wctomb_r,int,"_reent*, char*, wchar_t, _mbstate_t*" +Function,-,a64l,long,const char* +Function,+,abort,void, +Function,-,abs,int,int +Function,-,acos,double,double +Function,-,acosf,float,float +Function,-,acosh,double,double +Function,-,acoshf,float,float +Function,-,acoshl,long double,long double +Function,-,acosl,long double,long double +Function,+,acquire_mutex,void*,"ValueMutex*, uint32_t" +Function,-,aligned_alloc,void*,"size_t, size_t" +Function,-,aligned_free,void,void* +Function,-,aligned_malloc,void*,"size_t, size_t" +Function,-,arc4random,__uint32_t, +Function,-,arc4random_buf,void,"void*, size_t" +Function,-,arc4random_uniform,__uint32_t,__uint32_t +Function,+,args_char_to_hex,_Bool,"char, char, uint8_t*" +Function,+,args_get_first_word_length,size_t,string_t +Function,+,args_length,size_t,string_t +Function,+,args_read_hex_bytes,_Bool,"string_t, uint8_t*, size_t" +Function,+,args_read_int_and_trim,_Bool,"string_t, int*" +Function,+,args_read_probably_quoted_string_and_trim,_Bool,"string_t, string_t" +Function,+,args_read_string_and_trim,_Bool,"string_t, string_t" +Function,-,asin,double,double +Function,-,asinf,float,float +Function,-,asinh,double,double +Function,-,asinhf,float,float +Function,-,asinhl,long double,long double +Function,-,asinl,long double,long double +Function,-,asiprintf,int,"char**, const char*, ..." +Function,-,asniprintf,char*,"char*, size_t*, const char*, ..." +Function,-,asnprintf,char*,"char*, size_t*, const char*, ..." +Function,-,asprintf,int,"char**, const char*, ..." +Function,-,at_quick_exit,int,void (*)() +Function,-,atan,double,double +Function,-,atan2,double,"double, double" +Function,-,atan2f,float,"float, float" +Function,-,atan2l,long double,"long double, long double" +Function,-,atanf,float,float +Function,-,atanh,double,double +Function,-,atanhf,float,float +Function,-,atanhl,long double,long double +Function,-,atanl,long double,long double +Function,-,atexit,int,void (*)() +Function,-,atof,double,const char* +Function,-,atoff,float,const char* +Function,+,atoi,int,const char* +Function,-,atol,long,const char* +Function,-,atoll,long long,const char* +Function,-,basename,char*,const char* +Function,-,bcmp,int,"const void*, const void*, size_t" +Function,-,bcopy,void,"const void*, void*, size_t" +Function,+,bit_lib_add_parity,size_t,"const uint8_t*, size_t, uint8_t*, size_t, uint8_t, uint8_t, BitLibParity" +Function,+,bit_lib_copy_bits,void,"uint8_t*, size_t, size_t, const uint8_t*, size_t" +Function,+,bit_lib_crc16,uint16_t,"const uint8_t*, size_t, uint16_t, uint16_t, _Bool, _Bool, uint16_t" +Function,+,bit_lib_crc8,uint16_t,"const uint8_t*, size_t, uint8_t, uint8_t, _Bool, _Bool, uint8_t" +Function,+,bit_lib_get_bit,_Bool,"const uint8_t*, size_t" +Function,+,bit_lib_get_bit_count,uint8_t,uint32_t +Function,+,bit_lib_get_bits,uint8_t,"const uint8_t*, size_t, uint8_t" +Function,+,bit_lib_get_bits_16,uint16_t,"const uint8_t*, size_t, uint8_t" +Function,+,bit_lib_get_bits_32,uint32_t,"const uint8_t*, size_t, uint8_t" +Function,+,bit_lib_print_bits,void,"const uint8_t*, size_t" +Function,+,bit_lib_print_regions,void,"const BitLibRegion*, size_t, const uint8_t*, size_t" +Function,+,bit_lib_push_bit,void,"uint8_t*, size_t, _Bool" +Function,+,bit_lib_remove_bit_every_nth,size_t,"uint8_t*, size_t, uint8_t, uint8_t" +Function,+,bit_lib_reverse_16_fast,uint16_t,uint16_t +Function,+,bit_lib_reverse_8_fast,uint8_t,uint8_t +Function,+,bit_lib_reverse_bits,void,"uint8_t*, size_t, uint8_t" +Function,+,bit_lib_set_bit,void,"uint8_t*, size_t, _Bool" +Function,+,bit_lib_set_bits,void,"uint8_t*, size_t, uint8_t, uint8_t" +Function,+,bit_lib_test_parity,_Bool,"const uint8_t*, size_t, uint8_t, BitLibParity, uint8_t" +Function,+,bit_lib_test_parity_32,_Bool,"uint32_t, BitLibParity" +Function,+,ble_app_get_key_storage_buff,void,"uint8_t**, uint16_t*" +Function,+,ble_app_init,_Bool, +Function,+,ble_app_thread_stop,void, +Function,+,ble_glue_force_c2_mode,BleGlueCommandResult,BleGlueC2Mode +Function,-,ble_glue_fus_get_status,BleGlueCommandResult, +Function,-,ble_glue_fus_stack_delete,BleGlueCommandResult, +Function,-,ble_glue_fus_stack_install,BleGlueCommandResult,"uint32_t, uint32_t" +Function,-,ble_glue_fus_wait_operation,BleGlueCommandResult, +Function,+,ble_glue_get_c2_info,const BleGlueC2Info*, +Function,-,ble_glue_get_c2_status,BleGlueStatus, +Function,+,ble_glue_init,void, +Function,+,ble_glue_is_alive,_Bool, +Function,+,ble_glue_is_radio_stack_ready,_Bool, +Function,+,ble_glue_reinit_c2,_Bool, +Function,+,ble_glue_set_key_storage_changed_callback,void,"BleGlueKeyStorageChangedCallback, void*" +Function,+,ble_glue_start,_Bool, +Function,+,ble_glue_thread_stop,void, +Function,+,ble_glue_wait_for_c2_start,_Bool,int32_t +Function,-,bsearch,void*,"const void*, const void*, size_t, size_t, __compar_fn_t" +Function,+,bt_disconnect,void,Bt* +Function,+,bt_forget_bonded_devices,void,Bt* +Function,+,bt_set_profile,_Bool,"Bt*, BtProfile" +Function,+,bt_set_status_changed_callback,void,"Bt*, BtStatusChangedCallback, void*" +Function,+,buffered_file_stream_alloc,Stream*,Storage* +Function,+,buffered_file_stream_close,_Bool,Stream* +Function,+,buffered_file_stream_get_error,FS_Error,Stream* +Function,+,buffered_file_stream_open,_Bool,"Stream*, const char*, FS_AccessMode, FS_OpenMode" +Function,+,buffered_file_stream_sync,_Bool,Stream* +Function,+,button_menu_add_item,ButtonMenuItem*,"ButtonMenu*, const char*, int32_t, ButtonMenuItemCallback, ButtonMenuItemType, void*" +Function,+,button_menu_alloc,ButtonMenu*, +Function,+,button_menu_free,void,ButtonMenu* +Function,+,button_menu_get_view,View*,ButtonMenu* +Function,+,button_menu_reset,void,ButtonMenu* +Function,+,button_menu_set_header,void,"ButtonMenu*, const char*" +Function,+,button_menu_set_selected_item,void,"ButtonMenu*, uint32_t" +Function,+,button_panel_add_item,void,"ButtonPanel*, uint32_t, uint16_t, uint16_t, uint16_t, uint16_t, const Icon*, const Icon*, ButtonItemCallback, void*" +Function,+,button_panel_add_label,void,"ButtonPanel*, uint16_t, uint16_t, Font, const char*" +Function,+,button_panel_alloc,ButtonPanel*, +Function,+,button_panel_free,void,ButtonPanel* +Function,+,button_panel_get_view,View*,ButtonPanel* +Function,+,button_panel_reserve,void,"ButtonPanel*, size_t, size_t" +Function,+,button_panel_reset,void,ButtonPanel* +Function,+,byte_input_alloc,ByteInput*, +Function,+,byte_input_free,void,ByteInput* +Function,+,byte_input_get_view,View*,ByteInput* +Function,+,byte_input_set_header_text,void,"ByteInput*, const char*" +Function,+,byte_input_set_result_callback,void,"ByteInput*, ByteInputCallback, ByteChangedCallback, void*, uint8_t*, uint8_t" +Function,-,bzero,void,"void*, size_t" +Function,-,calloc,void*,"size_t, size_t" +Function,+,canvas_clear,void,Canvas* +Function,+,canvas_current_font_height,uint8_t,Canvas* +Function,+,canvas_draw_bitmap,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, const uint8_t*" +Function,+,canvas_draw_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" +Function,+,canvas_draw_circle,void,"Canvas*, uint8_t, uint8_t, uint8_t" +Function,+,canvas_draw_disc,void,"Canvas*, uint8_t, uint8_t, uint8_t" +Function,+,canvas_draw_dot,void,"Canvas*, uint8_t, uint8_t" +Function,+,canvas_draw_frame,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" +Function,+,canvas_draw_glyph,void,"Canvas*, uint8_t, uint8_t, uint16_t" +Function,+,canvas_draw_icon,void,"Canvas*, uint8_t, uint8_t, const Icon*" +Function,+,canvas_draw_icon_animation,void,"Canvas*, uint8_t, uint8_t, IconAnimation*" +Function,+,canvas_draw_line,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" +Function,+,canvas_draw_rbox,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t" +Function,+,canvas_draw_rframe,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t" +Function,+,canvas_draw_str,void,"Canvas*, uint8_t, uint8_t, const char*" +Function,+,canvas_draw_str_aligned,void,"Canvas*, uint8_t, uint8_t, Align, Align, const char*" +Function,+,canvas_draw_triangle,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, CanvasDirection" +Function,+,canvas_draw_xbm,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, const uint8_t*" +Function,+,canvas_get_font_params,CanvasFontParameters*,"Canvas*, Font" +Function,+,canvas_glyph_width,uint8_t,"Canvas*, char" +Function,+,canvas_height,uint8_t,Canvas* +Function,+,canvas_invert_color,void,Canvas* +Function,+,canvas_set_bitmap_mode,void,"Canvas*, _Bool" +Function,+,canvas_set_color,void,"Canvas*, Color" +Function,+,canvas_set_font,void,"Canvas*, Font" +Function,+,canvas_set_font_direction,void,"Canvas*, CanvasDirection" +Function,+,canvas_string_width,uint16_t,"Canvas*, const char*" +Function,+,canvas_width,uint8_t,Canvas* +Function,-,cbrt,double,double +Function,-,cbrtf,float,float +Function,-,cbrtl,long double,long double +Function,+,cc1101_calibrate,void,FuriHalSpiBusHandle* +Function,+,cc1101_flush_rx,void,FuriHalSpiBusHandle* +Function,+,cc1101_flush_tx,void,FuriHalSpiBusHandle* +Function,-,cc1101_get_partnumber,uint8_t,FuriHalSpiBusHandle* +Function,+,cc1101_get_rssi,uint8_t,FuriHalSpiBusHandle* +Function,+,cc1101_get_status,CC1101Status,FuriHalSpiBusHandle* +Function,-,cc1101_get_version,uint8_t,FuriHalSpiBusHandle* +Function,+,cc1101_read_fifo,uint8_t,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*" +Function,+,cc1101_read_reg,CC1101Status,"FuriHalSpiBusHandle*, uint8_t, uint8_t*" +Function,+,cc1101_reset,void,FuriHalSpiBusHandle* +Function,+,cc1101_set_frequency,uint32_t,"FuriHalSpiBusHandle*, uint32_t" +Function,-,cc1101_set_intermediate_frequency,uint32_t,"FuriHalSpiBusHandle*, uint32_t" +Function,+,cc1101_set_pa_table,void,"FuriHalSpiBusHandle*, const uint8_t[8]" +Function,+,cc1101_shutdown,void,FuriHalSpiBusHandle* +Function,+,cc1101_strobe,CC1101Status,"FuriHalSpiBusHandle*, uint8_t" +Function,+,cc1101_switch_to_idle,void,FuriHalSpiBusHandle* +Function,+,cc1101_switch_to_rx,void,FuriHalSpiBusHandle* +Function,+,cc1101_switch_to_tx,void,FuriHalSpiBusHandle* +Function,+,cc1101_write_fifo,uint8_t,"FuriHalSpiBusHandle*, const uint8_t*, uint8_t" +Function,+,cc1101_write_reg,CC1101Status,"FuriHalSpiBusHandle*, uint8_t, uint8_t" +Function,-,ceil,double,double +Function,-,ceilf,float,float +Function,-,ceill,long double,long double +Function,-,cfree,void,void* +Function,-,clearerr,void,FILE* +Function,-,clearerr_unlocked,void,FILE* +Function,+,cli_add_command,void,"Cli*, const char*, CliCommandFlag, CliCallback, void*" +Function,+,cli_cmd_interrupt_received,_Bool,Cli* +Function,+,cli_delete_command,void,"Cli*, const char*" +Function,+,cli_getc,char,Cli* +Function,+,cli_is_connected,_Bool,Cli* +Function,+,cli_nl,void, +Function,+,cli_print_usage,void,"const char*, const char*, const char*" +Function,+,cli_read,size_t,"Cli*, uint8_t*, size_t" +Function,+,cli_read_timeout,size_t,"Cli*, uint8_t*, size_t, uint32_t" +Function,+,cli_session_close,void,Cli* +Function,+,cli_session_open,void,"Cli*, void*" +Function,+,cli_write,void,"Cli*, const uint8_t*, size_t" +Function,-,copysign,double,"double, double" +Function,-,copysignf,float,"float, float" +Function,-,copysignl,long double,"long double, long double" +Function,-,cos,double,double +Function,-,cosf,float,float +Function,-,cosh,double,double +Function,-,coshf,float,float +Function,-,coshl,long double,long double +Function,-,cosl,long double,long double +Function,+,crc32_calc_buffer,uint32_t,"uint32_t, const void*, size_t" +Function,+,crc32_calc_file,uint32_t,"File*, const FileCrcProgressCb, void*" +Function,-,ctermid,char*,char* +Function,-,cuserid,char*,char* +Function,+,delete_mutex,_Bool,ValueMutex* +Function,+,dialog_ex_alloc,DialogEx*, +Function,+,dialog_ex_disable_extended_events,void,DialogEx* +Function,+,dialog_ex_enable_extended_events,void,DialogEx* +Function,+,dialog_ex_free,void,DialogEx* +Function,+,dialog_ex_get_view,View*,DialogEx* +Function,+,dialog_ex_reset,void,DialogEx* +Function,+,dialog_ex_set_center_button_text,void,"DialogEx*, const char*" +Function,+,dialog_ex_set_context,void,"DialogEx*, void*" +Function,+,dialog_ex_set_header,void,"DialogEx*, const char*, uint8_t, uint8_t, Align, Align" +Function,+,dialog_ex_set_icon,void,"DialogEx*, uint8_t, uint8_t, const Icon*" +Function,+,dialog_ex_set_left_button_text,void,"DialogEx*, const char*" +Function,+,dialog_ex_set_result_callback,void,"DialogEx*, DialogExResultCallback" +Function,+,dialog_ex_set_right_button_text,void,"DialogEx*, const char*" +Function,+,dialog_ex_set_text,void,"DialogEx*, const char*, uint8_t, uint8_t, Align, Align" +Function,+,dialog_file_browser_set_basic_options,void,"DialogsFileBrowserOptions*, const char*, const Icon*" +Function,+,dialog_file_browser_show,_Bool,"DialogsApp*, string_ptr, string_ptr, const DialogsFileBrowserOptions*" +Function,+,dialog_message_alloc,DialogMessage*, +Function,+,dialog_message_free,void,DialogMessage* +Function,+,dialog_message_set_buttons,void,"DialogMessage*, const char*, const char*, const char*" +Function,+,dialog_message_set_header,void,"DialogMessage*, const char*, uint8_t, uint8_t, Align, Align" +Function,+,dialog_message_set_icon,void,"DialogMessage*, const Icon*, uint8_t, uint8_t" +Function,+,dialog_message_set_text,void,"DialogMessage*, const char*, uint8_t, uint8_t, Align, Align" +Function,+,dialog_message_show,DialogMessageButton,"DialogsApp*, const DialogMessage*" +Function,+,dialog_message_show_storage_error,void,"DialogsApp*, const char*" +Function,-,digital_signal_alloc,DigitalSignal*,uint32_t +Function,-,digital_signal_append,_Bool,"DigitalSignal*, DigitalSignal*" +Function,-,digital_signal_free,void,DigitalSignal* +Function,-,digital_signal_get_edge,uint32_t,"DigitalSignal*, uint32_t" +Function,-,digital_signal_get_edges_cnt,uint32_t,DigitalSignal* +Function,-,digital_signal_get_start_level,_Bool,DigitalSignal* +Function,-,digital_signal_prepare_arr,void,DigitalSignal* +Function,-,digital_signal_send,void,"DigitalSignal*, const GpioPin*" +Function,-,diprintf,int,"int, const char*, ..." +Function,+,dir_walk_alloc,DirWalk*,Storage* +Function,+,dir_walk_close,void,DirWalk* +Function,+,dir_walk_free,void,DirWalk* +Function,+,dir_walk_get_error,FS_Error,DirWalk* +Function,+,dir_walk_open,_Bool,"DirWalk*, const char*" +Function,+,dir_walk_read,DirWalkResult,"DirWalk*, string_t, FileInfo*" +Function,+,dir_walk_set_filter_cb,void,"DirWalk*, DirWalkFilterCb, void*" +Function,+,dir_walk_set_recursive,void,"DirWalk*, _Bool" +Function,-,div,div_t,"int, int" +Function,+,dolphin_deed,void,"Dolphin*, DolphinDeed" +Function,+,dolphin_deed_get_app,DolphinApp,DolphinDeed +Function,+,dolphin_deed_get_app_limit,uint8_t,DolphinApp +Function,+,dolphin_deed_get_weight,uint8_t,DolphinDeed +Function,+,dolphin_flush,void,Dolphin* +Function,+,dolphin_get_pubsub,FuriPubSub*,Dolphin* +Function,+,dolphin_stats,DolphinStats,Dolphin* +Function,+,dolphin_upgrade_level,void,Dolphin* +Function,-,dprintf,int,"int, const char*, ..." +Function,-,drand48,double, +Function,-,drem,double,"double, double" +Function,-,dremf,float,"float, float" +Function,-,eTaskConfirmSleepModeStatus,eSleepModeStatus, +Function,-,eTaskGetState,eTaskState,TaskHandle_t +Function,+,elements_bold_rounded_frame,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" +Function,+,elements_bubble,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" +Function,+,elements_bubble_str,void,"Canvas*, uint8_t, uint8_t, const char*, Align, Align" +Function,+,elements_button_center,void,"Canvas*, const char*" +Function,+,elements_button_left,void,"Canvas*, const char*" +Function,+,elements_button_right,void,"Canvas*, const char*" +Function,+,elements_frame,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" +Function,+,elements_multiline_text,void,"Canvas*, uint8_t, uint8_t, const char*" +Function,+,elements_multiline_text_aligned,void,"Canvas*, uint8_t, uint8_t, Align, Align, const char*" +Function,+,elements_multiline_text_framed,void,"Canvas*, uint8_t, uint8_t, const char*" +Function,+,elements_progress_bar,void,"Canvas*, uint8_t, uint8_t, uint8_t, float" +Function,+,elements_scrollbar,void,"Canvas*, uint16_t, uint16_t" +Function,+,elements_scrollbar_pos,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t" +Function,+,elements_slightly_rounded_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" +Function,+,elements_slightly_rounded_frame,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" +Function,+,elements_string_fit_width,void,"Canvas*, string_t, uint8_t" +Function,+,elements_text_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, Align, Align, const char*, _Bool" +Function,+,empty_screen_alloc,EmptyScreen*, +Function,+,empty_screen_free,void,EmptyScreen* +Function,+,empty_screen_get_view,View*,EmptyScreen* +Function,-,erand48,double,unsigned short[3] +Function,-,erf,double,double +Function,-,erfc,double,double +Function,-,erfcf,float,float +Function,-,erfcl,long double,long double +Function,-,erff,float,float +Function,-,erfl,long double,long double +Function,-,exit,void,int +Function,-,exp,double,double +Function,-,exp10,double,double +Function,-,exp10f,float,float +Function,-,exp2,double,double +Function,-,exp2f,float,float +Function,-,exp2l,long double,long double +Function,-,expf,float,float +Function,-,expl,long double,long double +Function,-,explicit_bzero,void,"void*, size_t" +Function,-,expm1,double,double +Function,-,expm1f,float,float +Function,-,expm1l,long double,long double +Function,-,fabs,double,double +Function,-,fabsf,float,float +Function,-,fabsl,long double,long double +Function,-,fclose,int,FILE* +Function,-,fcloseall,int, +Function,-,fdim,double,"double, double" +Function,-,fdimf,float,"float, float" +Function,-,fdiml,long double,"long double, long double" +Function,-,fdopen,FILE*,"int, const char*" +Function,-,feof,int,FILE* +Function,-,feof_unlocked,int,FILE* +Function,-,ferror,int,FILE* +Function,-,ferror_unlocked,int,FILE* +Function,-,fflush,int,FILE* +Function,-,fflush_unlocked,int,FILE* +Function,-,ffs,int,int +Function,-,ffsl,int,long +Function,-,ffsll,int,long long +Function,-,fgetc,int,FILE* +Function,-,fgetc_unlocked,int,FILE* +Function,-,fgetpos,int,"FILE*, fpos_t*" +Function,-,fgets,char*,"char*, int, FILE*" +Function,-,fgets_unlocked,char*,"char*, int, FILE*" +Function,+,file_browser_alloc,FileBrowser*,string_ptr +Function,+,file_browser_configure,void,"FileBrowser*, const char*, _Bool, const Icon*, _Bool" +Function,+,file_browser_free,void,FileBrowser* +Function,+,file_browser_get_view,View*,FileBrowser* +Function,+,file_browser_set_callback,void,"FileBrowser*, FileBrowserCallback, void*" +Function,+,file_browser_set_item_callback,void,"FileBrowser*, FileBrowserLoadItemCallback, void*" +Function,+,file_browser_start,void,"FileBrowser*, string_t" +Function,+,file_browser_stop,void,FileBrowser* +Function,+,file_browser_worker_alloc,BrowserWorker*,"string_t, const char*, _Bool" +Function,+,file_browser_worker_folder_enter,void,"BrowserWorker*, string_t, int32_t" +Function,+,file_browser_worker_folder_exit,void,BrowserWorker* +Function,+,file_browser_worker_folder_refresh,void,"BrowserWorker*, int32_t" +Function,+,file_browser_worker_free,void,BrowserWorker* +Function,+,file_browser_worker_load,void,"BrowserWorker*, uint32_t, uint32_t" +Function,+,file_browser_worker_set_callback_context,void,"BrowserWorker*, void*" +Function,+,file_browser_worker_set_config,void,"BrowserWorker*, string_t, const char*, _Bool" +Function,+,file_browser_worker_set_folder_callback,void,"BrowserWorker*, BrowserWorkerFolderOpenCallback" +Function,+,file_browser_worker_set_item_callback,void,"BrowserWorker*, BrowserWorkerListItemCallback" +Function,+,file_browser_worker_set_list_callback,void,"BrowserWorker*, BrowserWorkerListLoadCallback" +Function,+,file_browser_worker_set_long_load_callback,void,"BrowserWorker*, BrowserWorkerLongLoadCallback" +Function,+,file_stream_alloc,Stream*,Storage* +Function,+,file_stream_close,_Bool,Stream* +Function,+,file_stream_get_error,FS_Error,Stream* +Function,+,file_stream_open,_Bool,"Stream*, const char*, FS_AccessMode, FS_OpenMode" +Function,-,fileno,int,FILE* +Function,-,fileno_unlocked,int,FILE* +Function,+,filesystem_api_error_get_desc,const char*,FS_Error +Function,-,finite,int,double +Function,-,finitef,int,float +Function,-,finitel,int,long double +Function,-,fiprintf,int,"FILE*, const char*, ..." +Function,-,fiscanf,int,"FILE*, const char*, ..." +Function,+,flipper_application_alloc,FlipperApplication*,"Storage*, const ElfApiInterface*" +Function,+,flipper_application_free,void,FlipperApplication* +Function,-,flipper_application_get_entry_address,const void*,FlipperApplication* +Function,+,flipper_application_get_manifest,const FlipperApplicationManifest*,FlipperApplication* +Function,-,flipper_application_get_state,const FlipperApplicationState*,FlipperApplication* +Function,-,flipper_application_get_thread,FuriThread*,FlipperApplication* +Function,+,flipper_application_load_status_to_string,const char*,FlipperApplicationLoadStatus +Function,+,flipper_application_map_to_memory,FlipperApplicationLoadStatus,FlipperApplication* +Function,+,flipper_application_preload,FlipperApplicationPreloadStatus,"FlipperApplication*, const char*" +Function,-,flipper_application_preload_status_to_string,const char*,FlipperApplicationPreloadStatus +Function,+,flipper_application_spawn,FuriThread*,"FlipperApplication*, void*" +Function,+,flipper_format_buffered_file_alloc,FlipperFormat*,Storage* +Function,+,flipper_format_buffered_file_close,_Bool,FlipperFormat* +Function,+,flipper_format_buffered_file_open_existing,_Bool,"FlipperFormat*, const char*" +Function,+,flipper_format_delete_key,_Bool,"FlipperFormat*, const char*" +Function,+,flipper_format_file_alloc,FlipperFormat*,Storage* +Function,+,flipper_format_file_close,_Bool,FlipperFormat* +Function,+,flipper_format_file_open_always,_Bool,"FlipperFormat*, const char*" +Function,+,flipper_format_file_open_append,_Bool,"FlipperFormat*, const char*" +Function,+,flipper_format_file_open_existing,_Bool,"FlipperFormat*, const char*" +Function,+,flipper_format_file_open_new,_Bool,"FlipperFormat*, const char*" +Function,+,flipper_format_free,void,FlipperFormat* +Function,+,flipper_format_get_raw_stream,Stream*,FlipperFormat* +Function,+,flipper_format_get_value_count,_Bool,"FlipperFormat*, const char*, uint32_t*" +Function,+,flipper_format_insert_or_update_bool,_Bool,"FlipperFormat*, const char*, const _Bool*, const uint16_t" +Function,+,flipper_format_insert_or_update_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t" +Function,+,flipper_format_insert_or_update_hex,_Bool,"FlipperFormat*, const char*, const uint8_t*, const uint16_t" +Function,+,flipper_format_insert_or_update_int32,_Bool,"FlipperFormat*, const char*, const int32_t*, const uint16_t" +Function,+,flipper_format_insert_or_update_string,_Bool,"FlipperFormat*, const char*, string_t" +Function,+,flipper_format_insert_or_update_string_cstr,_Bool,"FlipperFormat*, const char*, const char*" +Function,+,flipper_format_insert_or_update_uint32,_Bool,"FlipperFormat*, const char*, const uint32_t*, const uint16_t" +Function,+,flipper_format_key_exist,_Bool,"FlipperFormat*, const char*" +Function,+,flipper_format_read_bool,_Bool,"FlipperFormat*, const char*, _Bool*, const uint16_t" +Function,+,flipper_format_read_float,_Bool,"FlipperFormat*, const char*, float*, const uint16_t" +Function,+,flipper_format_read_header,_Bool,"FlipperFormat*, string_t, uint32_t*" +Function,+,flipper_format_read_hex,_Bool,"FlipperFormat*, const char*, uint8_t*, const uint16_t" +Function,+,flipper_format_read_hex_uint64,_Bool,"FlipperFormat*, const char*, uint64_t*, const uint16_t" +Function,+,flipper_format_read_int32,_Bool,"FlipperFormat*, const char*, int32_t*, const uint16_t" +Function,+,flipper_format_read_string,_Bool,"FlipperFormat*, const char*, string_t" +Function,+,flipper_format_read_uint32,_Bool,"FlipperFormat*, const char*, uint32_t*, const uint16_t" +Function,+,flipper_format_rewind,_Bool,FlipperFormat* +Function,+,flipper_format_seek_to_end,_Bool,FlipperFormat* +Function,+,flipper_format_set_strict_mode,void,"FlipperFormat*, _Bool" +Function,+,flipper_format_string_alloc,FlipperFormat*, +Function,+,flipper_format_update_bool,_Bool,"FlipperFormat*, const char*, const _Bool*, const uint16_t" +Function,+,flipper_format_update_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t" +Function,+,flipper_format_update_hex,_Bool,"FlipperFormat*, const char*, const uint8_t*, const uint16_t" +Function,+,flipper_format_update_int32,_Bool,"FlipperFormat*, const char*, const int32_t*, const uint16_t" +Function,+,flipper_format_update_string,_Bool,"FlipperFormat*, const char*, string_t" +Function,+,flipper_format_update_string_cstr,_Bool,"FlipperFormat*, const char*, const char*" +Function,+,flipper_format_update_uint32,_Bool,"FlipperFormat*, const char*, const uint32_t*, const uint16_t" +Function,+,flipper_format_write_bool,_Bool,"FlipperFormat*, const char*, const _Bool*, const uint16_t" +Function,+,flipper_format_write_comment,_Bool,"FlipperFormat*, string_t" +Function,+,flipper_format_write_comment_cstr,_Bool,"FlipperFormat*, const char*" +Function,+,flipper_format_write_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t" +Function,+,flipper_format_write_header,_Bool,"FlipperFormat*, string_t, const uint32_t" +Function,+,flipper_format_write_header_cstr,_Bool,"FlipperFormat*, const char*, const uint32_t" +Function,+,flipper_format_write_hex,_Bool,"FlipperFormat*, const char*, const uint8_t*, const uint16_t" +Function,+,flipper_format_write_hex_uint64,_Bool,"FlipperFormat*, const char*, const uint64_t*, const uint16_t" +Function,+,flipper_format_write_int32,_Bool,"FlipperFormat*, const char*, const int32_t*, const uint16_t" +Function,+,flipper_format_write_string,_Bool,"FlipperFormat*, const char*, string_t" +Function,+,flipper_format_write_string_cstr,_Bool,"FlipperFormat*, const char*, const char*" +Function,+,flipper_format_write_uint32,_Bool,"FlipperFormat*, const char*, const uint32_t*, const uint16_t" +Function,-,flockfile,void,FILE* +Function,-,floor,double,double +Function,-,floorf,float,float +Function,-,floorl,long double,long double +Function,-,fls,int,int +Function,-,flsl,int,long +Function,-,flsll,int,long long +Function,-,fma,double,"double, double, double" +Function,-,fmaf,float,"float, float, float" +Function,-,fmal,long double,"long double, long double, long double" +Function,-,fmax,double,"double, double" +Function,-,fmaxf,float,"float, float" +Function,-,fmaxl,long double,"long double, long double" +Function,-,fmemopen,FILE*,"void*, size_t, const char*" +Function,-,fmin,double,"double, double" +Function,-,fminf,float,"float, float" +Function,-,fminl,long double,"long double, long double" +Function,-,fmod,double,"double, double" +Function,-,fmodf,float,"float, float" +Function,-,fmodl,long double,"long double, long double" +Function,-,fopen,FILE*,"const char*, const char*" +Function,-,fopencookie,FILE*,"void*, const char*, cookie_io_functions_t" +Function,-,fprintf,int,"FILE*, const char*, ..." +Function,-,fpurge,int,FILE* +Function,-,fputc,int,"int, FILE*" +Function,-,fputc_unlocked,int,"int, FILE*" +Function,-,fputs,int,"const char*, FILE*" +Function,-,fputs_unlocked,int,"const char*, FILE*" +Function,-,fread,size_t,"void*, size_t, size_t, FILE*" +Function,-,fread_unlocked,size_t,"void*, size_t, size_t, FILE*" +Function,+,free,void,void* +Function,-,freopen,FILE*,"const char*, const char*, FILE*" +Function,-,frexp,double,"double, int*" +Function,-,frexpf,float,"float, int*" +Function,-,frexpl,long double,"long double, int*" +Function,-,fscanf,int,"FILE*, const char*, ..." +Function,-,fseek,int,"FILE*, long, int" +Function,-,fseeko,int,"FILE*, off_t, int" +Function,-,fsetpos,int,"FILE*, const fpos_t*" +Function,-,ftell,long,FILE* +Function,-,ftello,off_t,FILE* +Function,-,ftrylockfile,int,FILE* +Function,-,funlockfile,void,FILE* +Function,-,funopen,FILE*,"const void*, int (*)(void*, char*, int), int (*)(void*, const char*, int), fpos_t (*)(void*, fpos_t, int), int (*)(void*)" +Function,+,furi_crash,void,const char* +Function,+,furi_delay_ms,void,uint32_t +Function,+,furi_delay_tick,void,uint32_t +Function,+,furi_delay_until_tick,FuriStatus,uint32_t +Function,+,furi_delay_us,void,uint32_t +Function,+,furi_event_flag_alloc,FuriEventFlag*, +Function,+,furi_event_flag_clear,uint32_t,"FuriEventFlag*, uint32_t" +Function,+,furi_event_flag_free,void,FuriEventFlag* +Function,+,furi_event_flag_get,uint32_t,FuriEventFlag* +Function,+,furi_event_flag_set,uint32_t,"FuriEventFlag*, uint32_t" +Function,+,furi_event_flag_wait,uint32_t,"FuriEventFlag*, uint32_t, uint32_t, uint32_t" +Function,+,furi_get_tick,uint32_t, +Function,+,furi_hal_bt_change_app,_Bool,"FuriHalBtProfile, GapEventCallback, void*" +Function,+,furi_hal_bt_clear_white_list,_Bool, +Function,+,furi_hal_bt_dump_state,void,string_t +Function,+,furi_hal_bt_ensure_c2_mode,_Bool,BleGlueC2Mode +Function,+,furi_hal_bt_get_key_storage_buff,void,"uint8_t**, uint16_t*" +Function,+,furi_hal_bt_get_radio_stack,FuriHalBtStack, +Function,+,furi_hal_bt_get_rssi,float, +Function,+,furi_hal_bt_get_transmitted_packets,uint32_t, +Function,+,furi_hal_bt_hid_consumer_key_press,_Bool,uint16_t +Function,+,furi_hal_bt_hid_consumer_key_release,_Bool,uint16_t +Function,+,furi_hal_bt_hid_consumer_key_release_all,_Bool, +Function,+,furi_hal_bt_hid_kb_press,_Bool,uint16_t +Function,+,furi_hal_bt_hid_kb_release,_Bool,uint16_t +Function,+,furi_hal_bt_hid_kb_release_all,_Bool, +Function,+,furi_hal_bt_hid_mouse_move,_Bool,"int8_t, int8_t" +Function,+,furi_hal_bt_hid_mouse_press,_Bool,uint8_t +Function,+,furi_hal_bt_hid_mouse_release,_Bool,uint8_t +Function,+,furi_hal_bt_hid_mouse_release_all,_Bool, +Function,+,furi_hal_bt_hid_mouse_scroll,_Bool,int8_t +Function,+,furi_hal_bt_hid_start,void, +Function,+,furi_hal_bt_hid_stop,void, +Function,-,furi_hal_bt_init,void, +Function,+,furi_hal_bt_is_active,_Bool, +Function,+,furi_hal_bt_is_alive,_Bool, +Function,+,furi_hal_bt_is_ble_gatt_gap_supported,_Bool, +Function,+,furi_hal_bt_is_testing_supported,_Bool, +Function,+,furi_hal_bt_lock_core2,void, +Function,+,furi_hal_bt_nvm_sram_sem_acquire,void, +Function,+,furi_hal_bt_nvm_sram_sem_release,void, +Function,+,furi_hal_bt_reinit,void, +Function,+,furi_hal_bt_serial_notify_buffer_is_empty,void, +Function,+,furi_hal_bt_serial_set_event_callback,void,"uint16_t, FuriHalBtSerialCallback, void*" +Function,+,furi_hal_bt_serial_start,void, +Function,+,furi_hal_bt_serial_stop,void, +Function,+,furi_hal_bt_serial_tx,_Bool,"uint8_t*, uint16_t" +Function,+,furi_hal_bt_set_key_storage_change_callback,void,"BleGlueKeyStorageChangedCallback, void*" +Function,+,furi_hal_bt_start_advertising,void, +Function,+,furi_hal_bt_start_app,_Bool,"FuriHalBtProfile, GapEventCallback, void*" +Function,+,furi_hal_bt_start_packet_rx,void,"uint8_t, uint8_t" +Function,+,furi_hal_bt_start_packet_tx,void,"uint8_t, uint8_t, uint8_t" +Function,+,furi_hal_bt_start_radio_stack,_Bool, +Function,+,furi_hal_bt_start_rx,void,uint8_t +Function,+,furi_hal_bt_start_tone_tx,void,"uint8_t, uint8_t" +Function,+,furi_hal_bt_stop_advertising,void, +Function,+,furi_hal_bt_stop_packet_test,uint16_t, +Function,+,furi_hal_bt_stop_rx,void, +Function,+,furi_hal_bt_stop_tone_tx,void, +Function,+,furi_hal_bt_unlock_core2,void, +Function,+,furi_hal_bt_update_battery_level,void,uint8_t +Function,+,furi_hal_bt_update_power_state,void, +Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t +Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t +Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t" +Function,+,furi_hal_cdc_send,void,"uint8_t, uint8_t*, uint16_t" +Function,+,furi_hal_cdc_set_callbacks,void,"uint8_t, CdcCallbacks*, void*" +Function,+,furi_hal_clock_deinit_early,void, +Function,-,furi_hal_clock_init,void, +Function,-,furi_hal_clock_init_early,void, +Function,-,furi_hal_clock_resume_tick,void, +Function,-,furi_hal_clock_suspend_tick,void, +Function,-,furi_hal_clock_switch_to_hsi,void, +Function,-,furi_hal_clock_switch_to_pll,void, +Function,-,furi_hal_compress_alloc,FuriHalCompress*,uint16_t +Function,-,furi_hal_compress_decode,_Bool,"FuriHalCompress*, uint8_t*, size_t, uint8_t*, size_t, size_t*" +Function,-,furi_hal_compress_encode,_Bool,"FuriHalCompress*, uint8_t*, size_t, uint8_t*, size_t, size_t*" +Function,-,furi_hal_compress_free,void,FuriHalCompress* +Function,-,furi_hal_compress_icon_decode,void,"const uint8_t*, uint8_t**" +Function,-,furi_hal_compress_icon_init,void, +Function,+,furi_hal_console_disable,void, +Function,+,furi_hal_console_enable,void, +Function,-,furi_hal_console_init,void, +Function,+,furi_hal_console_printf,void,"const char[], ..." +Function,+,furi_hal_console_puts,void,const char* +Function,+,furi_hal_console_set_tx_callback,void,"FuriHalConsoleTxCallback, void*" +Function,+,furi_hal_console_tx,void,"const uint8_t*, size_t" +Function,+,furi_hal_console_tx_with_new_line,void,"const uint8_t*, size_t" +Function,+,furi_hal_cortex_delay_us,void,uint32_t +Function,-,furi_hal_cortex_init_early,void, +Function,+,furi_hal_cortex_instructions_per_microsecond,uint32_t, +Function,+,furi_hal_crypto_decrypt,_Bool,"const uint8_t*, uint8_t*, size_t" +Function,+,furi_hal_crypto_encrypt,_Bool,"const uint8_t*, uint8_t*, size_t" +Function,-,furi_hal_crypto_init,void, +Function,+,furi_hal_crypto_store_add_key,_Bool,"FuriHalCryptoKey*, uint8_t*" +Function,+,furi_hal_crypto_store_load_key,_Bool,"uint8_t, const uint8_t*" +Function,+,furi_hal_crypto_store_unload_key,_Bool,uint8_t +Function,+,furi_hal_crypto_verify_enclave,_Bool,"uint8_t*, uint8_t*" +Function,+,furi_hal_crypto_verify_key,_Bool,uint8_t +Function,+,furi_hal_debug_disable,void, +Function,+,furi_hal_debug_enable,void, +Function,-,furi_hal_deinit_early,void, +Function,-,furi_hal_flash_erase,_Bool,uint8_t +Function,-,furi_hal_flash_get_base,size_t, +Function,-,furi_hal_flash_get_cycles_count,size_t, +Function,-,furi_hal_flash_get_free_end_address,const void*, +Function,-,furi_hal_flash_get_free_page_count,size_t, +Function,-,furi_hal_flash_get_free_page_start_address,size_t, +Function,-,furi_hal_flash_get_free_start_address,const void*, +Function,-,furi_hal_flash_get_page_number,int16_t,size_t +Function,-,furi_hal_flash_get_page_size,size_t, +Function,-,furi_hal_flash_get_read_block_size,size_t, +Function,-,furi_hal_flash_get_write_block_size,size_t, +Function,-,furi_hal_flash_init,void, +Function,-,furi_hal_flash_ob_apply,void, +Function,-,furi_hal_flash_ob_get_raw_ptr,const FuriHalFlashRawOptionByteData*, +Function,-,furi_hal_flash_ob_set_word,_Bool,"size_t, const uint32_t" +Function,-,furi_hal_flash_program_page,_Bool,"const uint8_t, const uint8_t*, uint16_t" +Function,-,furi_hal_flash_write_dword,_Bool,"size_t, uint64_t" +Function,+,furi_hal_gpio_add_int_callback,void,"const GpioPin*, GpioExtiCallback, void*" +Function,+,furi_hal_gpio_disable_int_callback,void,const GpioPin* +Function,+,furi_hal_gpio_enable_int_callback,void,const GpioPin* +Function,+,furi_hal_gpio_init,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed" +Function,+,furi_hal_gpio_init_ex,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed, const GpioAltFn" +Function,+,furi_hal_gpio_init_simple,void,"const GpioPin*, const GpioMode" +Function,+,furi_hal_gpio_remove_int_callback,void,const GpioPin* +Function,+,furi_hal_hid_consumer_key_press,_Bool,uint16_t +Function,+,furi_hal_hid_consumer_key_release,_Bool,uint16_t +Function,+,furi_hal_hid_get_led_state,uint8_t, +Function,+,furi_hal_hid_is_connected,_Bool, +Function,+,furi_hal_hid_kb_press,_Bool,uint16_t +Function,+,furi_hal_hid_kb_release,_Bool,uint16_t +Function,+,furi_hal_hid_kb_release_all,_Bool, +Function,+,furi_hal_hid_mouse_move,_Bool,"int8_t, int8_t" +Function,+,furi_hal_hid_mouse_press,_Bool,uint8_t +Function,+,furi_hal_hid_mouse_release,_Bool,uint8_t +Function,+,furi_hal_hid_mouse_scroll,_Bool,int8_t +Function,+,furi_hal_hid_set_state_callback,void,"HidStateCallback, void*" +Function,+,furi_hal_hid_u2f_get_request,uint32_t,uint8_t* +Function,+,furi_hal_hid_u2f_is_connected,_Bool, +Function,+,furi_hal_hid_u2f_send_response,void,"uint8_t*, uint8_t" +Function,+,furi_hal_hid_u2f_set_callback,void,"HidU2fCallback, void*" +Function,+,furi_hal_i2c_acquire,void,FuriHalI2cBusHandle* +Function,+,furi_hal_i2c_deinit_early,void, +Function,-,furi_hal_i2c_init,void, +Function,-,furi_hal_i2c_init_early,void, +Function,+,furi_hal_i2c_is_device_ready,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint32_t" +Function,+,furi_hal_i2c_read_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, uint8_t, uint32_t" +Function,+,furi_hal_i2c_read_reg_16,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint16_t*, uint32_t" +Function,+,furi_hal_i2c_read_reg_8,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, uint32_t" +Function,+,furi_hal_i2c_release,void,FuriHalI2cBusHandle* +Function,+,furi_hal_i2c_rx,_Bool,"FuriHalI2cBusHandle*, const uint8_t, uint8_t*, const uint8_t, uint32_t" +Function,+,furi_hal_i2c_trx,_Bool,"FuriHalI2cBusHandle*, const uint8_t, const uint8_t*, const uint8_t, uint8_t*, const uint8_t, uint32_t" +Function,+,furi_hal_i2c_tx,_Bool,"FuriHalI2cBusHandle*, const uint8_t, const uint8_t*, const uint8_t, uint32_t" +Function,+,furi_hal_i2c_write_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, uint8_t, uint32_t" +Function,+,furi_hal_i2c_write_reg_16,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint16_t, uint32_t" +Function,+,furi_hal_i2c_write_reg_8,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t, uint32_t" +Function,+,furi_hal_ibutton_add_interrupt,void,"GpioExtiCallback, void*" +Function,+,furi_hal_ibutton_emulate_set_next,void,uint32_t +Function,+,furi_hal_ibutton_emulate_start,void,"uint32_t, FuriHalIbuttonEmulateCallback, void*" +Function,+,furi_hal_ibutton_emulate_stop,void, +Function,-,furi_hal_ibutton_init,void, +Function,+,furi_hal_ibutton_pin_get_level,_Bool, +Function,+,furi_hal_ibutton_pin_high,void, +Function,+,furi_hal_ibutton_pin_low,void, +Function,+,furi_hal_ibutton_remove_interrupt,void, +Function,+,furi_hal_ibutton_start_drive,void, +Function,+,furi_hal_ibutton_start_drive_in_isr,void, +Function,+,furi_hal_ibutton_start_interrupt,void, +Function,+,furi_hal_ibutton_start_interrupt_in_isr,void, +Function,+,furi_hal_ibutton_stop,void, +Function,+,furi_hal_info_get,void,"FuriHalInfoValueCallback, void*" +Function,+,furi_hal_infrared_async_rx_set_capture_isr_callback,void,"FuriHalInfraredRxCaptureCallback, void*" +Function,+,furi_hal_infrared_async_rx_set_timeout,void,uint32_t +Function,+,furi_hal_infrared_async_rx_set_timeout_isr_callback,void,"FuriHalInfraredRxTimeoutCallback, void*" +Function,+,furi_hal_infrared_async_rx_start,void, +Function,+,furi_hal_infrared_async_rx_stop,void, +Function,+,furi_hal_infrared_async_tx_set_data_isr_callback,void,"FuriHalInfraredTxGetDataISRCallback, void*" +Function,+,furi_hal_infrared_async_tx_set_signal_sent_isr_callback,void,"FuriHalInfraredTxSignalSentISRCallback, void*" +Function,+,furi_hal_infrared_async_tx_start,void,"uint32_t, float" +Function,+,furi_hal_infrared_async_tx_stop,void, +Function,+,furi_hal_infrared_async_tx_wait_termination,void, +Function,+,furi_hal_infrared_is_busy,_Bool, +Function,-,furi_hal_init,void, +Function,-,furi_hal_init_early,void, +Function,-,furi_hal_interrupt_init,void, +Function,+,furi_hal_interrupt_set_isr,void,"FuriHalInterruptId, FuriHalInterruptISR, void*" +Function,+,furi_hal_interrupt_set_isr_ex,void,"FuriHalInterruptId, uint16_t, FuriHalInterruptISR, void*" +Function,+,furi_hal_light_blink_set_color,void,Light +Function,+,furi_hal_light_blink_start,void,"Light, uint8_t, uint16_t, uint16_t" +Function,+,furi_hal_light_blink_stop,void, +Function,-,furi_hal_light_init,void, +Function,+,furi_hal_light_sequence,void,const char* +Function,+,furi_hal_light_set,void,"Light, uint8_t" +Function,+,furi_hal_memory_alloc,void*,size_t +Function,+,furi_hal_memory_get_free,size_t, +Function,+,furi_hal_memory_init,void, +Function,+,furi_hal_memory_max_pool_block,size_t, +Function,+,furi_hal_mpu_disable,void, +Function,+,furi_hal_mpu_enable,void, +Function,-,furi_hal_mpu_init,void, +Function,+,furi_hal_mpu_protect_disable,void,FuriHalMpuRegion +Function,+,furi_hal_mpu_protect_no_access,void,"FuriHalMpuRegion, uint32_t, FuriHalMPURegionSize" +Function,+,furi_hal_mpu_protect_read_only,void,"FuriHalMpuRegion, uint32_t, FuriHalMPURegionSize" +Function,+,furi_hal_nfc_activate_nfca,_Bool,"uint32_t, uint32_t*" +Function,+,furi_hal_nfc_detect,_Bool,"FuriHalNfcDevData*, uint32_t" +Function,+,furi_hal_nfc_emulate_nfca,_Bool,"uint8_t*, uint8_t, uint8_t*, uint8_t, FuriHalNfcEmulateCallback, void*, uint32_t" +Function,+,furi_hal_nfc_exit_sleep,void, +Function,+,furi_hal_nfc_field_off,void, +Function,+,furi_hal_nfc_field_on,void, +Function,-,furi_hal_nfc_init,void, +Function,+,furi_hal_nfc_is_busy,_Bool, +Function,+,furi_hal_nfc_is_init,_Bool, +Function,+,furi_hal_nfc_listen,_Bool,"uint8_t*, uint8_t, uint8_t*, uint8_t, _Bool, uint32_t" +Function,+,furi_hal_nfc_listen_rx,_Bool,"FuriHalNfcTxRxContext*, uint32_t" +Function,+,furi_hal_nfc_listen_sleep,void, +Function,+,furi_hal_nfc_listen_start,void,FuriHalNfcDevData* +Function,+,furi_hal_nfc_ll_poll,void, +Function,+,furi_hal_nfc_ll_set_error_handling,void,FuriHalNfcErrorHandling +Function,+,furi_hal_nfc_ll_set_fdt_listen,void,uint32_t +Function,+,furi_hal_nfc_ll_set_fdt_poll,void,uint32_t +Function,+,furi_hal_nfc_ll_set_guard_time,void,uint32_t +Function,+,furi_hal_nfc_ll_set_mode,FuriHalNfcReturn,"FuriHalNfcMode, FuriHalNfcBitrate, FuriHalNfcBitrate" +Function,+,furi_hal_nfc_ll_txrx,FuriHalNfcReturn,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t" +Function,+,furi_hal_nfc_ll_txrx_off,void, +Function,+,furi_hal_nfc_ll_txrx_on,void, +Function,+,furi_hal_nfc_sleep,void, +Function,+,furi_hal_nfc_start_sleep,void, +Function,+,furi_hal_nfc_stop,void, +Function,+,furi_hal_nfc_stop_cmd,void, +Function,+,furi_hal_nfc_tx_rx,_Bool,"FuriHalNfcTxRxContext*, uint16_t" +Function,+,furi_hal_nfc_tx_rx_full,_Bool,FuriHalNfcTxRxContext* +Function,-,furi_hal_os_init,void, +Function,+,furi_hal_os_tick,void, +Function,+,furi_hal_power_check_otg_status,void, +Function,+,furi_hal_power_deep_sleep_available,_Bool, +Function,+,furi_hal_power_disable_external_3_3v,void, +Function,+,furi_hal_power_disable_otg,void, +Function,+,furi_hal_power_dump_state,void, +Function,+,furi_hal_power_enable_external_3_3v,void, +Function,+,furi_hal_power_enable_otg,void, +Function,+,furi_hal_power_gauge_is_ok,_Bool, +Function,+,furi_hal_power_get_bat_health_pct,uint8_t, +Function,+,furi_hal_power_get_battery_current,float,FuriHalPowerIC +Function,+,furi_hal_power_get_battery_design_capacity,uint32_t, +Function,+,furi_hal_power_get_battery_full_capacity,uint32_t, +Function,+,furi_hal_power_get_battery_remaining_capacity,uint32_t, +Function,+,furi_hal_power_get_battery_temperature,float,FuriHalPowerIC +Function,+,furi_hal_power_get_battery_voltage,float,FuriHalPowerIC +Function,+,furi_hal_power_get_pct,uint8_t, +Function,+,furi_hal_power_get_usb_voltage,float, +Function,+,furi_hal_power_info_get,void,"FuriHalPowerInfoCallback, void*" +Function,-,furi_hal_power_init,void, +Function,+,furi_hal_power_insomnia_enter,void, +Function,+,furi_hal_power_insomnia_exit,void, +Function,-,furi_hal_power_insomnia_level,uint16_t, +Function,+,furi_hal_power_is_charging,_Bool, +Function,+,furi_hal_power_is_otg_enabled,_Bool, +Function,+,furi_hal_power_off,void, +Function,+,furi_hal_power_reset,void, +Function,+,furi_hal_power_shutdown,void, +Function,+,furi_hal_power_sleep,void, +Function,+,furi_hal_power_sleep_available,_Bool, +Function,+,furi_hal_power_suppress_charge_enter,void, +Function,+,furi_hal_power_suppress_charge_exit,void, +Function,+,furi_hal_random_fill_buf,void,"uint8_t*, uint32_t" +Function,+,furi_hal_random_get,uint32_t, +Function,+,furi_hal_region_get,const FuriHalRegion*, +Function,+,furi_hal_region_get_band,const FuriHalRegionBand*,uint32_t +Function,+,furi_hal_region_get_name,const char*, +Function,-,furi_hal_region_init,void, +Function,+,furi_hal_region_is_frequency_allowed,_Bool,uint32_t +Function,+,furi_hal_region_is_provisioned,_Bool, +Function,+,furi_hal_region_set,void,FuriHalRegion* +Function,+,furi_hal_resources_deinit_early,void, +Function,-,furi_hal_resources_init,void, +Function,-,furi_hal_resources_init_early,void, +Function,+,furi_hal_rfid_change_read_config,void,"float, float" +Function,+,furi_hal_rfid_comp_set_callback,void,"FuriHalRfidCompCallback, void*" +Function,+,furi_hal_rfid_comp_start,void, +Function,+,furi_hal_rfid_comp_stop,void, +Function,-,furi_hal_rfid_init,void, +Function,+,furi_hal_rfid_pin_pull_pulldown,void, +Function,+,furi_hal_rfid_pin_pull_release,void, +Function,+,furi_hal_rfid_pins_emulate,void, +Function,+,furi_hal_rfid_pins_read,void, +Function,+,furi_hal_rfid_pins_reset,void, +Function,+,furi_hal_rfid_set_emulate_period,void,uint32_t +Function,+,furi_hal_rfid_set_emulate_pulse,void,uint32_t +Function,+,furi_hal_rfid_set_read_period,void,uint32_t +Function,+,furi_hal_rfid_set_read_pulse,void,uint32_t +Function,+,furi_hal_rfid_tim_emulate,void,float +Function,+,furi_hal_rfid_tim_emulate_dma_start,void,"uint32_t*, uint32_t*, size_t, FuriHalRfidDMACallback, void*" +Function,+,furi_hal_rfid_tim_emulate_dma_stop,void, +Function,+,furi_hal_rfid_tim_emulate_start,void,"FuriHalRfidEmulateCallback, void*" +Function,+,furi_hal_rfid_tim_emulate_stop,void, +Function,+,furi_hal_rfid_tim_read,void,"float, float" +Function,+,furi_hal_rfid_tim_read_capture_start,void,"FuriHalRfidReadCaptureCallback, void*" +Function,+,furi_hal_rfid_tim_read_capture_stop,void, +Function,+,furi_hal_rfid_tim_read_start,void, +Function,+,furi_hal_rfid_tim_read_stop,void, +Function,+,furi_hal_rfid_tim_reset,void, +Function,+,furi_hal_rtc_datetime_to_timestamp,uint32_t,FuriHalRtcDateTime* +Function,+,furi_hal_rtc_deinit_early,void, +Function,+,furi_hal_rtc_get_boot_mode,FuriHalRtcBootMode, +Function,+,furi_hal_rtc_get_datetime,void,FuriHalRtcDateTime* +Function,+,furi_hal_rtc_get_fault_data,uint32_t, +Function,+,furi_hal_rtc_get_log_level,uint8_t, +Function,+,furi_hal_rtc_get_pin_fails,uint32_t, +Function,+,furi_hal_rtc_get_register,uint32_t,FuriHalRtcRegister +Function,-,furi_hal_rtc_init,void, +Function,-,furi_hal_rtc_init_early,void, +Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag +Function,+,furi_hal_rtc_reset_flag,void,FuriHalRtcFlag +Function,+,furi_hal_rtc_set_boot_mode,void,FuriHalRtcBootMode +Function,+,furi_hal_rtc_set_datetime,void,FuriHalRtcDateTime* +Function,+,furi_hal_rtc_set_fault_data,void,uint32_t +Function,+,furi_hal_rtc_set_flag,void,FuriHalRtcFlag +Function,+,furi_hal_rtc_set_log_level,void,uint8_t +Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t +Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t" +Function,+,furi_hal_rtc_validate_datetime,_Bool,FuriHalRtcDateTime* +Function,-,furi_hal_speaker_init,void, +Function,+,furi_hal_speaker_set_volume,void,float +Function,+,furi_hal_speaker_start,void,"float, float" +Function,+,furi_hal_speaker_stop,void, +Function,+,furi_hal_spi_acquire,void,FuriHalSpiBusHandle* +Function,+,furi_hal_spi_bus_deinit,void,FuriHalSpiBus* +Function,+,furi_hal_spi_bus_handle_deinit,void,FuriHalSpiBusHandle* +Function,+,furi_hal_spi_bus_handle_init,void,FuriHalSpiBusHandle* +Function,+,furi_hal_spi_bus_init,void,FuriHalSpiBus* +Function,+,furi_hal_spi_bus_rx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_deinit_early,void, +Function,-,furi_hal_spi_init,void, +Function,+,furi_hal_spi_init_early,void, +Function,+,furi_hal_spi_release,void,FuriHalSpiBusHandle* +Function,-,furi_hal_subghz_dump_state,void, +Function,+,furi_hal_subghz_flush_rx,void, +Function,+,furi_hal_subghz_flush_tx,void, +Function,+,furi_hal_subghz_get_lqi,uint8_t, +Function,+,furi_hal_subghz_get_rssi,float, +Function,+,furi_hal_subghz_idle,void, +Function,-,furi_hal_subghz_init,void, +Function,+,furi_hal_subghz_is_async_tx_complete,_Bool, +Function,+,furi_hal_subghz_is_frequency_valid,_Bool,uint32_t +Function,+,furi_hal_subghz_is_rx_data_crc_valid,_Bool, +Function,+,furi_hal_subghz_load_custom_preset,void,uint8_t* +Function,+,furi_hal_subghz_load_patable,void,const uint8_t[8] +Function,+,furi_hal_subghz_load_preset,void,FuriHalSubGhzPreset +Function,+,furi_hal_subghz_load_registers,void,uint8_t* +Function,+,furi_hal_subghz_read_packet,void,"uint8_t*, uint8_t*" +Function,+,furi_hal_subghz_reset,void, +Function,+,furi_hal_subghz_rx,void, +Function,+,furi_hal_subghz_rx_pipe_not_empty,_Bool, +Function,+,furi_hal_subghz_set_frequency,uint32_t,uint32_t +Function,+,furi_hal_subghz_set_frequency_and_path,uint32_t,uint32_t +Function,+,furi_hal_subghz_set_path,void,FuriHalSubGhzPath +Function,-,furi_hal_subghz_shutdown,void, +Function,+,furi_hal_subghz_sleep,void, +Function,+,furi_hal_subghz_start_async_rx,void,"FuriHalSubGhzCaptureCallback, void*" +Function,+,furi_hal_subghz_start_async_tx,_Bool,"FuriHalSubGhzAsyncTxCallback, void*" +Function,+,furi_hal_subghz_stop_async_rx,void, +Function,+,furi_hal_subghz_stop_async_tx,void, +Function,+,furi_hal_subghz_tx,_Bool, +Function,+,furi_hal_subghz_write_packet,void,"const uint8_t*, uint8_t" +Function,+,furi_hal_switch,void,void* +Function,+,furi_hal_uart_deinit,void,FuriHalUartId +Function,+,furi_hal_uart_init,void,"FuriHalUartId, uint32_t" +Function,+,furi_hal_uart_resume,void,FuriHalUartId +Function,+,furi_hal_uart_set_br,void,"FuriHalUartId, uint32_t" +Function,+,furi_hal_uart_set_irq_cb,void,"FuriHalUartId, void (*)(UartIrqEvent, uint8_t, void*), void*" +Function,+,furi_hal_uart_suspend,void,FuriHalUartId +Function,+,furi_hal_uart_tx,void,"FuriHalUartId, uint8_t*, size_t" +Function,+,furi_hal_usb_disable,void, +Function,+,furi_hal_usb_enable,void, +Function,+,furi_hal_usb_get_config,FuriHalUsbInterface*, +Function,-,furi_hal_usb_init,void, +Function,+,furi_hal_usb_is_locked,_Bool, +Function,+,furi_hal_usb_lock,void, +Function,+,furi_hal_usb_reinit,void, +Function,+,furi_hal_usb_set_config,_Bool,"FuriHalUsbInterface*, void*" +Function,-,furi_hal_usb_set_state_callback,void,"FuriHalUsbStateCallback, void*" +Function,+,furi_hal_usb_unlock,void, +Function,+,furi_hal_version_do_i_belong_here,_Bool, +Function,+,furi_hal_version_get_ble_local_device_name_ptr,const char*, +Function,+,furi_hal_version_get_ble_mac,const uint8_t*, +Function,+,furi_hal_version_get_device_name_ptr,const char*, +Function,+,furi_hal_version_get_firmware_version,const Version*, +Function,+,furi_hal_version_get_hw_body,uint8_t, +Function,+,furi_hal_version_get_hw_color,FuriHalVersionColor, +Function,+,furi_hal_version_get_hw_connect,uint8_t, +Function,+,furi_hal_version_get_hw_display,FuriHalVersionDisplay, +Function,+,furi_hal_version_get_hw_region,FuriHalVersionRegion, +Function,+,furi_hal_version_get_hw_region_name,const char*, +Function,+,furi_hal_version_get_hw_target,uint8_t, +Function,+,furi_hal_version_get_hw_timestamp,uint32_t, +Function,+,furi_hal_version_get_hw_version,uint8_t, +Function,+,furi_hal_version_get_model_name,const char*, +Function,+,furi_hal_version_get_name_ptr,const char*, +Function,+,furi_hal_version_get_otp_version,FuriHalVersionOtpVersion, +Function,-,furi_hal_version_init,void, +Function,+,furi_hal_version_uid,const uint8_t*, +Function,+,furi_hal_version_uid_size,size_t, +Function,-,furi_hal_vibro_init,void, +Function,+,furi_hal_vibro_on,void,_Bool +Function,+,furi_halt,void,const char* +Function,-,furi_init,void, +Function,+,furi_kernel_get_tick_frequency,uint32_t, +Function,+,furi_kernel_lock,int32_t, +Function,+,furi_kernel_restore_lock,int32_t,int32_t +Function,+,furi_kernel_unlock,int32_t, +Function,+,furi_log_get_level,FuriLogLevel, +Function,-,furi_log_init,void, +Function,+,furi_log_print_format,void,"FuriLogLevel, const char*, const char*, ..." +Function,+,furi_log_set_level,void,FuriLogLevel +Function,-,furi_log_set_puts,void,FuriLogPuts +Function,-,furi_log_set_timestamp,void,FuriLogTimestamp +Function,+,furi_message_queue_alloc,FuriMessageQueue*,"uint32_t, uint32_t" +Function,+,furi_message_queue_free,void,FuriMessageQueue* +Function,+,furi_message_queue_get,FuriStatus,"FuriMessageQueue*, void*, uint32_t" +Function,+,furi_message_queue_get_capacity,uint32_t,FuriMessageQueue* +Function,+,furi_message_queue_get_count,uint32_t,FuriMessageQueue* +Function,+,furi_message_queue_get_message_size,uint32_t,FuriMessageQueue* +Function,+,furi_message_queue_get_space,uint32_t,FuriMessageQueue* +Function,+,furi_message_queue_put,FuriStatus,"FuriMessageQueue*, const void*, uint32_t" +Function,+,furi_message_queue_reset,FuriStatus,FuriMessageQueue* +Function,+,furi_ms_to_ticks,uint32_t,uint32_t +Function,+,furi_mutex_acquire,FuriStatus,"FuriMutex*, uint32_t" +Function,+,furi_mutex_alloc,FuriMutex*,FuriMutexType +Function,+,furi_mutex_free,void,FuriMutex* +Function,+,furi_mutex_get_owner,FuriThreadId,FuriMutex* +Function,+,furi_mutex_release,FuriStatus,FuriMutex* +Function,+,furi_pubsub_alloc,FuriPubSub*, +Function,-,furi_pubsub_free,void,FuriPubSub* +Function,+,furi_pubsub_publish,void,"FuriPubSub*, void*" +Function,+,furi_pubsub_subscribe,FuriPubSubSubscription*,"FuriPubSub*, FuriPubSubCallback, void*" +Function,+,furi_pubsub_unsubscribe,void,"FuriPubSub*, FuriPubSubSubscription*" +Function,+,furi_record_close,void,const char* +Function,+,furi_record_create,void,"const char*, void*" +Function,-,furi_record_destroy,_Bool,const char* +Function,+,furi_record_exists,_Bool,const char* +Function,-,furi_record_init,void, +Function,+,furi_record_open,void*,const char* +Function,+,furi_run,void, +Function,+,furi_semaphore_acquire,FuriStatus,"FuriSemaphore*, uint32_t" +Function,+,furi_semaphore_alloc,FuriSemaphore*,"uint32_t, uint32_t" +Function,+,furi_semaphore_free,void,FuriSemaphore* +Function,+,furi_semaphore_get_count,uint32_t,FuriSemaphore* +Function,+,furi_semaphore_release,FuriStatus,FuriSemaphore* +Function,+,furi_thread_alloc,FuriThread*, +Function,+,furi_thread_catch,void, +Function,-,furi_thread_disable_heap_trace,void,FuriThread* +Function,+,furi_thread_enable_heap_trace,void,FuriThread* +Function,+,furi_thread_enumerate,uint32_t,"FuriThreadId*, uint32_t" +Function,+,furi_thread_flags_clear,uint32_t,uint32_t +Function,+,furi_thread_flags_get,uint32_t, +Function,+,furi_thread_flags_set,uint32_t,"FuriThreadId, uint32_t" +Function,+,furi_thread_flags_wait,uint32_t,"uint32_t, uint32_t, uint32_t" +Function,+,furi_thread_free,void,FuriThread* +Function,+,furi_thread_get_current,FuriThread*, +Function,+,furi_thread_get_current_id,FuriThreadId, +Function,+,furi_thread_get_heap_size,size_t,FuriThread* +Function,+,furi_thread_get_id,FuriThreadId,FuriThread* +Function,+,furi_thread_get_name,const char*,FuriThreadId +Function,+,furi_thread_get_return_code,int32_t,FuriThread* +Function,+,furi_thread_get_stack_space,uint32_t,FuriThreadId +Function,+,furi_thread_get_state,FuriThreadState,FuriThread* +Function,+,furi_thread_is_suspended,_Bool,FuriThreadId +Function,+,furi_thread_join,_Bool,FuriThread* +Function,+,furi_thread_mark_as_service,void,FuriThread* +Function,+,furi_thread_resume,void,FuriThreadId +Function,+,furi_thread_set_callback,void,"FuriThread*, FuriThreadCallback" +Function,+,furi_thread_set_context,void,"FuriThread*, void*" +Function,+,furi_thread_set_name,void,"FuriThread*, const char*" +Function,+,furi_thread_set_priority,void,"FuriThread*, FuriThreadPriority" +Function,+,furi_thread_set_stack_size,void,"FuriThread*, size_t" +Function,+,furi_thread_set_state_callback,void,"FuriThread*, FuriThreadStateCallback" +Function,+,furi_thread_set_state_context,void,"FuriThread*, void*" +Function,+,furi_thread_set_stdout_callback,_Bool,FuriThreadStdoutWriteCallback +Function,+,furi_thread_start,void,FuriThread* +Function,+,furi_thread_stdout_flush,int32_t, +Function,+,furi_thread_stdout_write,size_t,"const char*, size_t" +Function,+,furi_thread_suspend,void,FuriThreadId +Function,+,furi_thread_yield,void, +Function,+,furi_timer_alloc,FuriTimer*,"FuriTimerCallback, FuriTimerType, void*" +Function,+,furi_timer_free,void,FuriTimer* +Function,+,furi_timer_is_running,uint32_t,FuriTimer* +Function,+,furi_timer_start,FuriStatus,"FuriTimer*, uint32_t" +Function,+,furi_timer_stop,FuriStatus,FuriTimer* +Function,-,fwrite,size_t,"const void*, size_t, size_t, FILE*" +Function,-,fwrite_unlocked,size_t,"const void*, size_t, size_t, FILE*" +Function,-,gamma,double,double +Function,-,gamma_r,double,"double, int*" +Function,-,gammaf,float,float +Function,-,gammaf_r,float,"float, int*" +Function,-,gap_get_state,GapState, +Function,-,gap_init,_Bool,"GapConfig*, GapEventCallback, void*" +Function,-,gap_start_advertising,void, +Function,-,gap_stop_advertising,void, +Function,-,gap_thread_stop,void, +Function,-,getc,int,FILE* +Function,-,getc_unlocked,int,FILE* +Function,-,getchar,int, +Function,-,getchar_unlocked,int, +Function,-,getenv,char*,const char* +Function,-,gets,char*,char* +Function,-,getsubopt,int,"char**, char**, char**" +Function,-,getw,int,FILE* +Function,+,gui_add_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*" +Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer" +Function,+,gui_get_framebuffer_size,size_t,Gui* +Function,+,gui_remove_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*" +Function,+,gui_remove_view_port,void,"Gui*, ViewPort*" +Function,+,gui_set_lockdown,void,"Gui*, _Bool" +Function,-,gui_view_port_send_to_back,void,"Gui*, ViewPort*" +Function,+,gui_view_port_send_to_front,void,"Gui*, ViewPort*" +Function,+,hal_sd_detect,_Bool, +Function,+,hal_sd_detect_init,void, +Function,+,hal_sd_detect_set_low,void, +Function,+,hmac_sha256_finish,void,"const hmac_sha256_context*, const uint8_t*, uint8_t*" +Function,+,hmac_sha256_init,void,"hmac_sha256_context*, const uint8_t*" +Function,+,hmac_sha256_update,void,"const hmac_sha256_context*, const uint8_t*, unsigned" +Function,-,hypot,double,"double, double" +Function,-,hypotf,float,"float, float" +Function,-,hypotl,long double,"long double, long double" +Function,+,ibutton_key_alloc,iButtonKey*, +Function,+,ibutton_key_clear_data,void,iButtonKey* +Function,+,ibutton_key_dallas_crc_is_valid,_Bool,iButtonKey* +Function,+,ibutton_key_dallas_is_1990_key,_Bool,iButtonKey* +Function,+,ibutton_key_free,void,iButtonKey* +Function,+,ibutton_key_get_data_p,const uint8_t*,iButtonKey* +Function,+,ibutton_key_get_data_size,uint8_t,iButtonKey* +Function,+,ibutton_key_get_max_size,uint8_t, +Function,+,ibutton_key_get_size_by_type,uint8_t,iButtonKeyType +Function,+,ibutton_key_get_string_by_type,const char*,iButtonKeyType +Function,+,ibutton_key_get_type,iButtonKeyType,iButtonKey* +Function,+,ibutton_key_get_type_by_string,_Bool,"const char*, iButtonKeyType*" +Function,+,ibutton_key_set,void,"iButtonKey*, const iButtonKey*" +Function,+,ibutton_key_set_data,void,"iButtonKey*, uint8_t*, uint8_t" +Function,+,ibutton_key_set_type,void,"iButtonKey*, iButtonKeyType" +Function,+,ibutton_worker_alloc,iButtonWorker*, +Function,+,ibutton_worker_emulate_set_callback,void,"iButtonWorker*, iButtonWorkerEmulateCallback, void*" +Function,+,ibutton_worker_emulate_start,void,"iButtonWorker*, iButtonKey*" +Function,+,ibutton_worker_free,void,iButtonWorker* +Function,+,ibutton_worker_read_set_callback,void,"iButtonWorker*, iButtonWorkerReadCallback, void*" +Function,+,ibutton_worker_read_start,void,"iButtonWorker*, iButtonKey*" +Function,+,ibutton_worker_start_thread,void,iButtonWorker* +Function,+,ibutton_worker_stop,void,iButtonWorker* +Function,+,ibutton_worker_stop_thread,void,iButtonWorker* +Function,+,ibutton_worker_write_set_callback,void,"iButtonWorker*, iButtonWorkerWriteCallback, void*" +Function,+,ibutton_worker_write_start,void,"iButtonWorker*, iButtonKey*" +Function,+,icon_animation_alloc,IconAnimation*,const Icon* +Function,+,icon_animation_free,void,IconAnimation* +Function,+,icon_animation_get_height,uint8_t,IconAnimation* +Function,+,icon_animation_get_width,uint8_t,IconAnimation* +Function,+,icon_animation_is_last_frame,_Bool,IconAnimation* +Function,+,icon_animation_set_update_callback,void,"IconAnimation*, IconAnimationCallback, void*" +Function,+,icon_animation_start,void,IconAnimation* +Function,+,icon_animation_stop,void,IconAnimation* +Function,+,icon_get_data,const uint8_t*,const Icon* +Function,+,icon_get_height,uint8_t,const Icon* +Function,+,icon_get_width,uint8_t,const Icon* +Function,-,ilogb,int,double +Function,-,ilogbf,int,float +Function,-,ilogbl,int,long double +Function,-,index,char*,"const char*, int" +Function,-,infinity,double, +Function,-,infinityf,float, +Function,+,init_mutex,_Bool,"ValueMutex*, void*, size_t" +Function,-,initstate,char*,"unsigned, char*, size_t" +Function,+,input_get_key_name,const char*,InputKey +Function,+,input_get_type_name,const char*,InputType +Function,-,iprintf,int,"const char*, ..." +Function,-,isalnum,int,int +Function,-,isalnum_l,int,"int, locale_t" +Function,-,isalpha,int,int +Function,-,isalpha_l,int,"int, locale_t" +Function,-,isascii,int,int +Function,-,isascii_l,int,"int, locale_t" +Function,-,isblank,int,int +Function,-,isblank_l,int,"int, locale_t" +Function,-,iscanf,int,"const char*, ..." +Function,-,iscntrl,int,int +Function,-,iscntrl_l,int,"int, locale_t" +Function,-,isdigit,int,int +Function,-,isdigit_l,int,"int, locale_t" +Function,-,isgraph,int,int +Function,-,isgraph_l,int,"int, locale_t" +Function,-,isinf,int,double +Function,-,isinff,int,float +Function,-,islower,int,int +Function,-,islower_l,int,"int, locale_t" +Function,-,isnan,int,double +Function,-,isnanf,int,float +Function,-,isprint,int,int +Function,-,isprint_l,int,"int, locale_t" +Function,-,ispunct,int,int +Function,-,ispunct_l,int,"int, locale_t" +Function,-,isspace,int,int +Function,-,isspace_l,int,"int, locale_t" +Function,-,isupper,int,int +Function,-,isupper_l,int,"int, locale_t" +Function,-,isxdigit,int,int +Function,-,isxdigit_l,int,"int, locale_t" +Function,-,itoa,char*,"int, char*, int" +Function,-,j0,double,double +Function,-,j0f,float,float +Function,-,j1,double,double +Function,-,j1f,float,float +Function,-,jn,double,"int, double" +Function,-,jnf,float,"int, float" +Function,-,jrand48,long,unsigned short[3] +Function,-,l64a,char*,long +Function,-,labs,long,long +Function,-,lcong48,void,unsigned short[7] +Function,-,ldexp,double,"double, int" +Function,-,ldexpf,float,"float, int" +Function,-,ldexpl,long double,"long double, int" +Function,-,ldiv,ldiv_t,"long, long" +Function,+,lfrfid_dict_file_load,ProtocolId,"ProtocolDict*, const char*" +Function,+,lfrfid_dict_file_save,_Bool,"ProtocolDict*, ProtocolId, const char*" +Function,+,lfrfid_raw_file_alloc,LFRFIDRawFile*,Storage* +Function,+,lfrfid_raw_file_free,void,LFRFIDRawFile* +Function,+,lfrfid_raw_file_open_read,_Bool,"LFRFIDRawFile*, const char*" +Function,+,lfrfid_raw_file_open_write,_Bool,"LFRFIDRawFile*, const char*" +Function,+,lfrfid_raw_file_read_header,_Bool,"LFRFIDRawFile*, float*, float*" +Function,+,lfrfid_raw_file_read_pair,_Bool,"LFRFIDRawFile*, uint32_t*, uint32_t*, _Bool*" +Function,+,lfrfid_raw_file_write_buffer,_Bool,"LFRFIDRawFile*, uint8_t*, size_t" +Function,+,lfrfid_raw_file_write_header,_Bool,"LFRFIDRawFile*, float, float, uint32_t" +Function,+,lfrfid_raw_worker_alloc,LFRFIDRawWorker*, +Function,+,lfrfid_raw_worker_free,void,LFRFIDRawWorker* +Function,+,lfrfid_raw_worker_start_emulate,void,"LFRFIDRawWorker*, const char*, LFRFIDWorkerEmulateRawCallback, void*" +Function,+,lfrfid_raw_worker_start_read,void,"LFRFIDRawWorker*, const char*, float, float, LFRFIDWorkerReadRawCallback, void*" +Function,+,lfrfid_raw_worker_stop,void,LFRFIDRawWorker* +Function,+,lfrfid_worker_alloc,LFRFIDWorker*,ProtocolDict* +Function,+,lfrfid_worker_emulate_raw_start,void,"LFRFIDWorker*, const char*, LFRFIDWorkerEmulateRawCallback, void*" +Function,+,lfrfid_worker_emulate_start,void,"LFRFIDWorker*, LFRFIDProtocol" +Function,+,lfrfid_worker_free,void,LFRFIDWorker* +Function,+,lfrfid_worker_read_raw_start,void,"LFRFIDWorker*, const char*, LFRFIDWorkerReadType, LFRFIDWorkerReadRawCallback, void*" +Function,+,lfrfid_worker_read_start,void,"LFRFIDWorker*, LFRFIDWorkerReadType, LFRFIDWorkerReadCallback, void*" +Function,+,lfrfid_worker_start_thread,void,LFRFIDWorker* +Function,+,lfrfid_worker_stop,void,LFRFIDWorker* +Function,+,lfrfid_worker_stop_thread,void,LFRFIDWorker* +Function,+,lfrfid_worker_write_start,void,"LFRFIDWorker*, LFRFIDProtocol, LFRFIDWorkerWriteCallback, void*" +Function,-,lgamma,double,double +Function,-,lgamma_r,double,"double, int*" +Function,-,lgammaf,float,float +Function,-,lgammaf_r,float,"float, int*" +Function,-,lgammal,long double,long double +Function,-,llabs,long long,long long +Function,-,lldiv,lldiv_t,"long long, long long" +Function,-,llrint,long long int,double +Function,-,llrintf,long long int,float +Function,-,llrintl,long long int,long double +Function,-,llround,long long int,double +Function,-,llroundf,long long int,float +Function,-,llroundl,long long int,long double +Function,+,loader_get_pubsub,FuriPubSub*,Loader* +Function,+,loader_is_locked,_Bool,Loader* +Function,+,loader_lock,_Bool,Loader* +Function,+,loader_show_menu,void, +Function,+,loader_start,LoaderStatus,"Loader*, const char*, const char*" +Function,+,loader_unlock,void,Loader* +Function,+,loader_update_menu,void, +Function,+,loading_alloc,Loading*, +Function,+,loading_free,void,Loading* +Function,+,loading_get_view,View*,Loading* +Function,-,log,double,double +Function,-,log10,double,double +Function,-,log10f,float,float +Function,-,log10l,long double,long double +Function,-,log1p,double,double +Function,-,log1pf,float,float +Function,-,log1pl,long double,long double +Function,-,log2,double,double +Function,-,log2f,float,float +Function,-,log2l,long double,long double +Function,-,logb,double,double +Function,-,logbf,float,float +Function,-,logbl,long double,long double +Function,-,logf,float,float +Function,-,logl,long double,long double +Function,-,lrand48,long, +Function,-,lrint,long int,double +Function,-,lrintf,long int,float +Function,-,lrintl,long int,long double +Function,-,lround,long int,double +Function,-,lroundf,long int,float +Function,-,lroundl,long,long double +Function,+,malloc,void*,size_t +Function,+,manchester_advance,_Bool,"ManchesterState, ManchesterEvent, ManchesterState*, _Bool*" +Function,+,manchester_encoder_advance,_Bool,"ManchesterEncoderState*, const _Bool, ManchesterEncoderResult*" +Function,+,manchester_encoder_finish,ManchesterEncoderResult,ManchesterEncoderState* +Function,+,manchester_encoder_reset,void,ManchesterEncoderState* +Function,+,maxim_crc8,uint8_t,"const uint8_t*, const uint8_t, const uint8_t" +Function,-,mblen,int,"const char*, size_t" +Function,-,mbstowcs,size_t,"wchar_t*, const char*, size_t" +Function,-,mbtowc,int,"wchar_t*, const char*, size_t" +Function,+,md5,void,"const unsigned char*, size_t, unsigned char[16]" +Function,+,md5_finish,void,"md5_context*, unsigned char[16]" +Function,+,md5_process,void,"md5_context*, const unsigned char[64]" +Function,+,md5_starts,void,md5_context* +Function,+,md5_update,void,"md5_context*, const unsigned char*, size_t" +Function,-,memccpy,void*,"void*, const void*, int, size_t" +Function,+,memchr,void*,"const void*, int, size_t" +Function,+,memcmp,int,"const void*, const void*, size_t" +Function,+,memcpy,void*,"void*, const void*, size_t" +Function,-,memmem,void*,"const void*, size_t, const void*, size_t" +Function,-,memmgr_alloc_from_pool,void*,size_t +Function,+,memmgr_get_free_heap,size_t, +Function,+,memmgr_get_minimum_free_heap,size_t, +Function,+,memmgr_get_total_heap,size_t, +Function,+,memmgr_heap_disable_thread_trace,void,FuriThreadId +Function,+,memmgr_heap_enable_thread_trace,void,FuriThreadId +Function,+,memmgr_heap_get_max_free_block,size_t, +Function,+,memmgr_heap_get_thread_memory,size_t,FuriThreadId +Function,+,memmgr_heap_printf_free_blocks,void, +Function,-,memmgr_pool_get_free,size_t, +Function,-,memmgr_pool_get_max_block,size_t, +Function,+,memmove,void*,"void*, const void*, size_t" +Function,-,mempcpy,void*,"void*, const void*, size_t" +Function,-,memrchr,void*,"const void*, int, size_t" +Function,+,memset,void*,"void*, int, size_t" +Function,+,menu_add_item,void,"Menu*, const char*, const Icon*, uint32_t, MenuItemCallback, void*" +Function,+,menu_alloc,Menu*, +Function,+,menu_free,void,Menu* +Function,+,menu_get_view,View*,Menu* +Function,+,menu_reset,void,Menu* +Function,+,menu_set_selected_item,void,"Menu*, uint32_t" +Function,-,mkdtemp,char*,char* +Function,-,mkostemp,int,"char*, int" +Function,-,mkostemps,int,"char*, int, int" +Function,-,mkstemp,int,char* +Function,-,mkstemps,int,"char*, int" +Function,-,mktemp,char*,char* +Function,-,modf,double,"double, double*" +Function,-,modff,float,"float, float*" +Function,-,modfl,long double,"long double, long double*" +Function,-,mrand48,long, +Function,-,nan,double,const char* +Function,-,nanf,float,const char* +Function,-,nanl,long double,const char* +Function,-,nearbyint,double,double +Function,-,nearbyintf,float,float +Function,-,nearbyintl,long double,long double +Function,-,nextafter,double,"double, double" +Function,-,nextafterf,float,"float, float" +Function,-,nextafterl,long double,"long double, long double" +Function,-,nexttoward,double,"double, long double" +Function,-,nexttowardf,float,"float, long double" +Function,-,nexttowardl,long double,"long double, long double" +Function,-,nfca_append_crc16,void,"uint8_t*, uint16_t" +Function,-,nfca_emulation_handler,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*" +Function,-,nfca_get_crc16,uint16_t,"uint8_t*, uint16_t" +Function,-,nfca_signal_alloc,NfcaSignal*, +Function,-,nfca_signal_encode,void,"NfcaSignal*, uint8_t*, uint16_t, uint8_t*" +Function,-,nfca_signal_free,void,NfcaSignal* +Function,+,notification_internal_message,void,"NotificationApp*, const NotificationSequence*" +Function,+,notification_internal_message_block,void,"NotificationApp*, const NotificationSequence*" +Function,+,notification_message,void,"NotificationApp*, const NotificationSequence*" +Function,+,notification_message_block,void,"NotificationApp*, const NotificationSequence*" +Function,-,nrand48,long,unsigned short[3] +Function,-,on_exit,int,"void (*)(int, void*), void*" +Function,+,onewire_device_alloc,OneWireDevice*,"uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t" +Function,+,onewire_device_attach,void,"OneWireDevice*, OneWireSlave*" +Function,+,onewire_device_detach,void,OneWireDevice* +Function,+,onewire_device_free,void,OneWireDevice* +Function,+,onewire_device_get_id_p,uint8_t*,OneWireDevice* +Function,+,onewire_device_send_id,void,OneWireDevice* +Function,+,onewire_host_alloc,OneWireHost*, +Function,+,onewire_host_free,void,OneWireHost* +Function,+,onewire_host_read,uint8_t,OneWireHost* +Function,+,onewire_host_read_bit,_Bool,OneWireHost* +Function,+,onewire_host_read_bytes,void,"OneWireHost*, uint8_t*, uint16_t" +Function,+,onewire_host_reset,_Bool,OneWireHost* +Function,+,onewire_host_reset_search,void,OneWireHost* +Function,+,onewire_host_search,uint8_t,"OneWireHost*, uint8_t*, OneWireHostSearchMode" +Function,+,onewire_host_skip,void,OneWireHost* +Function,+,onewire_host_start,void,OneWireHost* +Function,+,onewire_host_stop,void,OneWireHost* +Function,+,onewire_host_target_search,void,"OneWireHost*, uint8_t" +Function,+,onewire_host_write,void,"OneWireHost*, uint8_t" +Function,+,onewire_host_write_bit,void,"OneWireHost*, _Bool" +Function,+,onewire_slave_alloc,OneWireSlave*, +Function,+,onewire_slave_attach,void,"OneWireSlave*, OneWireDevice*" +Function,+,onewire_slave_detach,void,OneWireSlave* +Function,+,onewire_slave_free,void,OneWireSlave* +Function,+,onewire_slave_set_result_callback,void,"OneWireSlave*, OneWireSlaveResultCallback, void*" +Function,+,onewire_slave_start,void,OneWireSlave* +Function,+,onewire_slave_stop,void,OneWireSlave* +Function,-,open_memstream,FILE*,"char**, size_t*" +Function,+,path_append,void,"string_t, const char*" +Function,+,path_concat,void,"const char*, const char*, string_t" +Function,+,path_contains_only_ascii,_Bool,const char* +Function,+,path_extract_basename,void,"const char*, string_t" +Function,+,path_extract_dirname,void,"const char*, string_t" +Function,+,path_extract_extension,void,"string_t, char*, size_t" +Function,+,path_extract_filename,void,"string_t, string_t, _Bool" +Function,+,path_extract_filename_no_ext,void,"const char*, string_t" +Function,-,pcTaskGetName,char*,TaskHandle_t +Function,-,pcTimerGetName,const char*,TimerHandle_t +Function,-,pclose,int,FILE* +Function,-,perror,void,const char* +Function,-,platformDisableIrqCallback,void, +Function,-,platformEnableIrqCallback,void, +Function,-,platformProtectST25RComm,void, +Function,-,platformSetIrqCallback,void,PlatformIrqCallback +Function,-,platformSpiTxRx,_Bool,"const uint8_t*, uint8_t*, uint16_t" +Function,-,platformUnprotectST25RComm,void, +Function,-,popen,FILE*,"const char*, const char*" +Function,+,popup_alloc,Popup*, +Function,+,popup_disable_timeout,void,Popup* +Function,+,popup_enable_timeout,void,Popup* +Function,+,popup_free,void,Popup* +Function,+,popup_get_view,View*,Popup* +Function,+,popup_reset,void,Popup* +Function,+,popup_set_callback,void,"Popup*, PopupCallback" +Function,+,popup_set_context,void,"Popup*, void*" +Function,+,popup_set_header,void,"Popup*, const char*, uint8_t, uint8_t, Align, Align" +Function,+,popup_set_icon,void,"Popup*, uint8_t, uint8_t, const Icon*" +Function,+,popup_set_text,void,"Popup*, const char*, uint8_t, uint8_t, Align, Align" +Function,+,popup_set_timeout,void,"Popup*, uint32_t" +Function,-,posix_memalign,int,"void**, size_t, size_t" +Function,-,pow,double,"double, double" +Function,-,pow10,double,double +Function,-,pow10f,float,float +Function,-,power_enable_low_battery_level_notification,void,"Power*, _Bool" +Function,+,power_get_info,void,"Power*, PowerInfo*" +Function,+,power_get_pubsub,FuriPubSub*,Power* +Function,+,power_is_battery_healthy,_Bool,Power* +Function,+,power_off,void,Power* +Function,+,power_reboot,void,PowerBootMode +Function,+,powf,float,"float, float" +Function,-,powl,long double,"long double, long double" +Function,-,printf,int,"const char*, ..." +Function,+,protocol_dict_alloc,ProtocolDict*,"const ProtocolBase**, size_t" +Function,+,protocol_dict_decoders_feed,ProtocolId,"ProtocolDict*, _Bool, uint32_t" +Function,+,protocol_dict_decoders_feed_by_feature,ProtocolId,"ProtocolDict*, uint32_t, _Bool, uint32_t" +Function,+,protocol_dict_decoders_feed_by_id,ProtocolId,"ProtocolDict*, size_t, _Bool, uint32_t" +Function,+,protocol_dict_decoders_start,void,ProtocolDict* +Function,+,protocol_dict_encoder_start,_Bool,"ProtocolDict*, size_t" +Function,+,protocol_dict_encoder_yield,LevelDuration,"ProtocolDict*, size_t" +Function,+,protocol_dict_free,void,ProtocolDict* +Function,+,protocol_dict_get_data,void,"ProtocolDict*, size_t, uint8_t*, size_t" +Function,+,protocol_dict_get_data_size,size_t,"ProtocolDict*, size_t" +Function,+,protocol_dict_get_features,uint32_t,"ProtocolDict*, size_t" +Function,+,protocol_dict_get_manufacturer,const char*,"ProtocolDict*, size_t" +Function,+,protocol_dict_get_max_data_size,size_t,ProtocolDict* +Function,+,protocol_dict_get_name,const char*,"ProtocolDict*, size_t" +Function,+,protocol_dict_get_protocol_by_name,ProtocolId,"ProtocolDict*, const char*" +Function,+,protocol_dict_get_validate_count,uint32_t,"ProtocolDict*, size_t" +Function,+,protocol_dict_get_write_data,_Bool,"ProtocolDict*, size_t, void*" +Function,+,protocol_dict_render_brief_data,void,"ProtocolDict*, string_t, size_t" +Function,+,protocol_dict_render_data,void,"ProtocolDict*, string_t, size_t" +Function,+,protocol_dict_set_data,void,"ProtocolDict*, size_t, const uint8_t*, size_t" +Function,-,pselect,int,"int, fd_set*, fd_set*, fd_set*, const timespec*, const sigset_t*" +Function,-,putc,int,"int, FILE*" +Function,-,putc_unlocked,int,"int, FILE*" +Function,-,putchar,int,int +Function,-,putchar_unlocked,int,int +Function,-,putenv,int,char* +Function,-,puts,int,const char* +Function,-,putw,int,"int, FILE*" +Function,-,pvPortMalloc,void*,size_t +Function,-,pvTaskGetThreadLocalStoragePointer,void*,"TaskHandle_t, BaseType_t" +Function,-,pvTaskIncrementMutexHeldCount,TaskHandle_t, +Function,-,pvTimerGetTimerID,void*,const TimerHandle_t +Function,-,pxPortInitialiseStack,StackType_t*,"StackType_t*, TaskFunction_t, void*" +Function,-,qsort,void,"void*, size_t, size_t, __compar_fn_t" +Function,-,qsort_r,void,"void*, size_t, size_t, int (*)(const void*, const void*, void*), void*" +Function,-,quick_exit,void,int +Function,+,rand,int, +Function,-,rand_r,int,unsigned* +Function,+,random,long, +Function,-,rawmemchr,void*,"const void*, int" +Function,-,read_mutex,_Bool,"ValueMutex*, void*, size_t, uint32_t" +Function,+,realloc,void*,"void*, size_t" +Function,-,reallocarray,void*,"void*, size_t, size_t" +Function,-,reallocf,void*,"void*, size_t" +Function,-,realpath,char*,"const char*, char*" +Function,+,release_mutex,_Bool,"ValueMutex*, const void*" +Function,-,remainder,double,"double, double" +Function,-,remainderf,float,"float, float" +Function,-,remainderl,long double,"long double, long double" +Function,-,remove,int,const char* +Function,-,remquo,double,"double, double, int*" +Function,-,remquof,float,"float, float, int*" +Function,-,remquol,long double,"long double, long double, int*" +Function,-,rename,int,"const char*, const char*" +Function,-,renameat,int,"int, const char*, int, const char*" +Function,-,rewind,void,FILE* +Function,-,rfalAdjustRegulators,ReturnCode,uint16_t* +Function,-,rfalCalibrate,ReturnCode, +Function,-,rfalDeinitialize,ReturnCode, +Function,-,rfalDisableObsvMode,void, +Function,-,rfalFeliCaPoll,ReturnCode,"rfalFeliCaPollSlots, uint16_t, uint8_t, rfalFeliCaPollRes*, uint8_t, uint8_t*, uint8_t*" +Function,-,rfalFieldOff,ReturnCode, +Function,+,rfalFieldOnAndStartGT,ReturnCode, +Function,-,rfalGetBitRate,ReturnCode,"rfalBitRate*, rfalBitRate*" +Function,-,rfalGetErrorHandling,rfalEHandling, +Function,-,rfalGetFDTListen,uint32_t, +Function,-,rfalGetFDTPoll,uint32_t, +Function,-,rfalGetGT,uint32_t, +Function,-,rfalGetMode,rfalMode, +Function,-,rfalGetObsvMode,void,"uint8_t*, uint8_t*" +Function,-,rfalGetTransceiveRSSI,ReturnCode,uint16_t* +Function,-,rfalGetTransceiveState,rfalTransceiveState, +Function,-,rfalGetTransceiveStatus,ReturnCode, +Function,-,rfalISO14443ATransceiveAnticollisionFrame,ReturnCode,"uint8_t*, uint8_t*, uint8_t*, uint16_t*, uint32_t" +Function,-,rfalISO14443ATransceiveShortFrame,ReturnCode,"rfal14443AShortFrameCmd, uint8_t*, uint8_t, uint16_t*, uint32_t" +Function,-,rfalISO15693TransceiveAnticollisionFrame,ReturnCode,"uint8_t*, uint8_t, uint8_t*, uint8_t, uint16_t*" +Function,-,rfalISO15693TransceiveEOF,ReturnCode,"uint8_t*, uint8_t, uint16_t*" +Function,-,rfalISO15693TransceiveEOFAnticollision,ReturnCode,"uint8_t*, uint8_t, uint16_t*" +Function,-,rfalInitialize,ReturnCode, +Function,-,rfalIsExtFieldOn,_Bool, +Function,-,rfalIsGTExpired,_Bool, +Function,-,rfalIsTransceiveInRx,_Bool, +Function,-,rfalIsTransceiveInTx,_Bool, +Function,-,rfalIsoDepATTRIB,ReturnCode,"const uint8_t*, uint8_t, rfalBitRate, rfalBitRate, rfalIsoDepFSxI, uint8_t, uint8_t, const uint8_t*, uint8_t, uint32_t, rfalIsoDepAttribRes*, uint8_t*" +Function,-,rfalIsoDepDeselect,ReturnCode, +Function,-,rfalIsoDepFSxI2FSx,uint16_t,uint8_t +Function,-,rfalIsoDepFWI2FWT,uint32_t,uint8_t +Function,-,rfalIsoDepGetApduTransceiveStatus,ReturnCode, +Function,-,rfalIsoDepGetMaxInfLen,uint16_t, +Function,-,rfalIsoDepGetTransceiveStatus,ReturnCode, +Function,-,rfalIsoDepInitialize,void, +Function,-,rfalIsoDepInitializeWithParams,void,"rfalComplianceMode, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t" +Function,-,rfalIsoDepIsAttrib,_Bool,"const uint8_t*, uint8_t" +Function,-,rfalIsoDepIsRats,_Bool,"const uint8_t*, uint8_t" +Function,-,rfalIsoDepListenGetActivationStatus,ReturnCode, +Function,-,rfalIsoDepListenStartActivation,ReturnCode,"rfalIsoDepAtsParam*, const rfalIsoDepAttribResParam*, const uint8_t*, uint16_t, rfalIsoDepListenActvParam" +Function,-,rfalIsoDepPPS,ReturnCode,"uint8_t, rfalBitRate, rfalBitRate, rfalIsoDepPpsRes*" +Function,-,rfalIsoDepPollAGetActivationStatus,ReturnCode, +Function,-,rfalIsoDepPollAHandleActivation,ReturnCode,"rfalIsoDepFSxI, uint8_t, rfalBitRate, rfalIsoDepDevice*" +Function,-,rfalIsoDepPollAStartActivation,ReturnCode,"rfalIsoDepFSxI, uint8_t, rfalBitRate, rfalIsoDepDevice*" +Function,-,rfalIsoDepPollBGetActivationStatus,ReturnCode, +Function,-,rfalIsoDepPollBHandleActivation,ReturnCode,"rfalIsoDepFSxI, uint8_t, rfalBitRate, uint8_t, const rfalNfcbListenDevice*, const uint8_t*, uint8_t, rfalIsoDepDevice*" +Function,-,rfalIsoDepPollBStartActivation,ReturnCode,"rfalIsoDepFSxI, uint8_t, rfalBitRate, uint8_t, const rfalNfcbListenDevice*, const uint8_t*, uint8_t, rfalIsoDepDevice*" +Function,-,rfalIsoDepPollHandleSParameters,ReturnCode,"rfalIsoDepDevice*, rfalBitRate, rfalBitRate" +Function,-,rfalIsoDepRATS,ReturnCode,"rfalIsoDepFSxI, uint8_t, rfalIsoDepAts*, uint8_t*" +Function,-,rfalIsoDepStartApduTransceive,ReturnCode,rfalIsoDepApduTxRxParam +Function,-,rfalIsoDepStartTransceive,ReturnCode,rfalIsoDepTxRxParam +Function,-,rfalListenGetState,rfalLmState,"_Bool*, rfalBitRate*" +Function,-,rfalListenSetState,ReturnCode,rfalLmState +Function,-,rfalListenSleepStart,ReturnCode,"rfalLmState, uint8_t*, uint16_t, uint16_t*" +Function,-,rfalListenStart,ReturnCode,"uint32_t, const rfalLmConfPA*, const rfalLmConfPB*, const rfalLmConfPF*, uint8_t*, uint16_t, uint16_t*" +Function,-,rfalListenStop,ReturnCode, +Function,+,rfalLowPowerModeStart,ReturnCode, +Function,+,rfalLowPowerModeStop,ReturnCode, +Function,-,rfalNfcDataExchangeCustomStart,ReturnCode,"uint8_t*, uint16_t, uint8_t**, uint16_t**, uint32_t, uint32_t" +Function,-,rfalNfcDataExchangeGetStatus,ReturnCode, +Function,-,rfalNfcDataExchangeStart,ReturnCode,"uint8_t*, uint16_t, uint8_t**, uint16_t**, uint32_t, uint32_t" +Function,-,rfalNfcDeactivate,ReturnCode,_Bool +Function,-,rfalNfcDepATR,ReturnCode,"const rfalNfcDepAtrParam*, rfalNfcDepAtrRes*, uint8_t*" +Function,-,rfalNfcDepCalculateRWT,uint32_t,uint8_t +Function,-,rfalNfcDepDSL,ReturnCode, +Function,-,rfalNfcDepGetPduTransceiveStatus,ReturnCode, +Function,-,rfalNfcDepGetTransceiveStatus,ReturnCode, +Function,-,rfalNfcDepInitialize,void, +Function,-,rfalNfcDepInitiatorHandleActivation,ReturnCode,"rfalNfcDepAtrParam*, rfalBitRate, rfalNfcDepDevice*" +Function,-,rfalNfcDepIsAtrReq,_Bool,"const uint8_t*, uint16_t, uint8_t*" +Function,-,rfalNfcDepListenGetActivationStatus,ReturnCode, +Function,-,rfalNfcDepListenStartActivation,ReturnCode,"const rfalNfcDepTargetParam*, const uint8_t*, uint16_t, rfalNfcDepListenActvParam" +Function,-,rfalNfcDepPSL,ReturnCode,"uint8_t, uint8_t" +Function,-,rfalNfcDepRLS,ReturnCode, +Function,-,rfalNfcDepSetDeactivatingCallback,void,rfalNfcDepDeactCallback +Function,-,rfalNfcDepStartPduTransceive,ReturnCode,rfalNfcDepPduTxRxParam +Function,-,rfalNfcDepStartTransceive,ReturnCode,const rfalNfcDepTxRxParam* +Function,-,rfalNfcDepTargetRcvdATR,_Bool, +Function,-,rfalNfcDiscover,ReturnCode,const rfalNfcDiscoverParam* +Function,-,rfalNfcGetActiveDevice,ReturnCode,rfalNfcDevice** +Function,-,rfalNfcGetDevicesFound,ReturnCode,"rfalNfcDevice**, uint8_t*" +Function,-,rfalNfcGetState,rfalNfcState, +Function,-,rfalNfcInitialize,ReturnCode, +Function,-,rfalNfcSelect,ReturnCode,uint8_t +Function,-,rfalNfcWorker,void, +Function,-,rfalNfcaListenerIsSleepReq,_Bool,"const uint8_t*, uint16_t" +Function,-,rfalNfcaPollerCheckPresence,ReturnCode,"rfal14443AShortFrameCmd, rfalNfcaSensRes*" +Function,-,rfalNfcaPollerFullCollisionResolution,ReturnCode,"rfalComplianceMode, uint8_t, rfalNfcaListenDevice*, uint8_t*" +Function,-,rfalNfcaPollerGetFullCollisionResolutionStatus,ReturnCode, +Function,-,rfalNfcaPollerInitialize,ReturnCode, +Function,-,rfalNfcaPollerSelect,ReturnCode,"const uint8_t*, uint8_t, rfalNfcaSelRes*" +Function,-,rfalNfcaPollerSingleCollisionResolution,ReturnCode,"uint8_t, _Bool*, rfalNfcaSelRes*, uint8_t*, uint8_t*" +Function,-,rfalNfcaPollerSleep,ReturnCode, +Function,-,rfalNfcaPollerSleepFullCollisionResolution,ReturnCode,"uint8_t, rfalNfcaListenDevice*, uint8_t*" +Function,-,rfalNfcaPollerStartFullCollisionResolution,ReturnCode,"rfalComplianceMode, uint8_t, rfalNfcaListenDevice*, uint8_t*" +Function,-,rfalNfcaPollerTechnologyDetection,ReturnCode,"rfalComplianceMode, rfalNfcaSensRes*" +Function,-,rfalNfcbPollerCheckPresence,ReturnCode,"rfalNfcbSensCmd, rfalNfcbSlots, rfalNfcbSensbRes*, uint8_t*" +Function,-,rfalNfcbPollerCollisionResolution,ReturnCode,"rfalComplianceMode, uint8_t, rfalNfcbListenDevice*, uint8_t*" +Function,-,rfalNfcbPollerInitialize,ReturnCode, +Function,-,rfalNfcbPollerInitializeWithParams,ReturnCode,"uint8_t, uint8_t" +Function,-,rfalNfcbPollerSleep,ReturnCode,const uint8_t* +Function,-,rfalNfcbPollerSlotMarker,ReturnCode,"uint8_t, rfalNfcbSensbRes*, uint8_t*" +Function,-,rfalNfcbPollerSlottedCollisionResolution,ReturnCode,"rfalComplianceMode, uint8_t, rfalNfcbSlots, rfalNfcbSlots, rfalNfcbListenDevice*, uint8_t*, _Bool*" +Function,-,rfalNfcbPollerTechnologyDetection,ReturnCode,"rfalComplianceMode, rfalNfcbSensbRes*, uint8_t*" +Function,-,rfalNfcbTR2ToFDT,uint32_t,uint8_t +Function,-,rfalNfcfListenerIsT3TReq,_Bool,"const uint8_t*, uint16_t, uint8_t*" +Function,-,rfalNfcfPollerCheck,ReturnCode,"const uint8_t*, const rfalNfcfServBlockListParam*, uint8_t*, uint16_t, uint16_t*" +Function,-,rfalNfcfPollerCheckPresence,ReturnCode, +Function,-,rfalNfcfPollerCollisionResolution,ReturnCode,"rfalComplianceMode, uint8_t, rfalNfcfListenDevice*, uint8_t*" +Function,-,rfalNfcfPollerInitialize,ReturnCode,rfalBitRate +Function,-,rfalNfcfPollerPoll,ReturnCode,"rfalFeliCaPollSlots, uint16_t, uint8_t, rfalFeliCaPollRes*, uint8_t*, uint8_t*" +Function,-,rfalNfcfPollerUpdate,ReturnCode,"const uint8_t*, const rfalNfcfServBlockListParam*, uint8_t*, uint16_t, const uint8_t*, uint8_t*, uint16_t" +Function,-,rfalNfcvPollerCheckPresence,ReturnCode,rfalNfcvInventoryRes* +Function,-,rfalNfcvPollerCollisionResolution,ReturnCode,"rfalComplianceMode, uint8_t, rfalNfcvListenDevice*, uint8_t*" +Function,-,rfalNfcvPollerExtendedGetSystemInformation,ReturnCode,"uint8_t, const uint8_t*, uint8_t, uint8_t*, uint16_t, uint16_t*" +Function,-,rfalNfcvPollerExtendedLockSingleBlock,ReturnCode,"uint8_t, const uint8_t*, uint16_t" +Function,-,rfalNfcvPollerExtendedReadMultipleBlocks,ReturnCode,"uint8_t, const uint8_t*, uint16_t, uint16_t, uint8_t*, uint16_t, uint16_t*" +Function,-,rfalNfcvPollerExtendedReadSingleBlock,ReturnCode,"uint8_t, const uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*" +Function,-,rfalNfcvPollerExtendedWriteMultipleBlocks,ReturnCode,"uint8_t, const uint8_t*, uint16_t, uint16_t, uint8_t*, uint16_t, uint8_t, const uint8_t*, uint16_t" +Function,-,rfalNfcvPollerExtendedWriteSingleBlock,ReturnCode,"uint8_t, const uint8_t*, uint16_t, const uint8_t*, uint8_t" +Function,-,rfalNfcvPollerGetSystemInformation,ReturnCode,"uint8_t, const uint8_t*, uint8_t*, uint16_t, uint16_t*" +Function,-,rfalNfcvPollerInitialize,ReturnCode, +Function,-,rfalNfcvPollerInventory,ReturnCode,"rfalNfcvNumSlots, uint8_t, const uint8_t*, rfalNfcvInventoryRes*, uint16_t*" +Function,-,rfalNfcvPollerLockBlock,ReturnCode,"uint8_t, const uint8_t*, uint8_t" +Function,-,rfalNfcvPollerReadMultipleBlocks,ReturnCode,"uint8_t, const uint8_t*, uint8_t, uint8_t, uint8_t*, uint16_t, uint16_t*" +Function,-,rfalNfcvPollerReadSingleBlock,ReturnCode,"uint8_t, const uint8_t*, uint8_t, uint8_t*, uint16_t, uint16_t*" +Function,-,rfalNfcvPollerSelect,ReturnCode,"uint8_t, const uint8_t*" +Function,-,rfalNfcvPollerSleep,ReturnCode,"uint8_t, const uint8_t*" +Function,-,rfalNfcvPollerSleepCollisionResolution,ReturnCode,"uint8_t, rfalNfcvListenDevice*, uint8_t*" +Function,-,rfalNfcvPollerTransceiveReq,ReturnCode,"uint8_t, uint8_t, uint8_t, const uint8_t*, const uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*" +Function,-,rfalNfcvPollerWriteMultipleBlocks,ReturnCode,"uint8_t, const uint8_t*, uint8_t, uint8_t, uint8_t*, uint16_t, uint8_t, const uint8_t*, uint16_t" +Function,-,rfalNfcvPollerWriteSingleBlock,ReturnCode,"uint8_t, const uint8_t*, uint8_t, const uint8_t*, uint8_t" +Function,-,rfalSetBitRate,ReturnCode,"rfalBitRate, rfalBitRate" +Function,-,rfalSetErrorHandling,void,rfalEHandling +Function,-,rfalSetFDTListen,void,uint32_t +Function,-,rfalSetFDTPoll,void,uint32_t +Function,-,rfalSetGT,void,uint32_t +Function,-,rfalSetMode,ReturnCode,"rfalMode, rfalBitRate, rfalBitRate" +Function,-,rfalSetObsvMode,void,"uint8_t, uint8_t" +Function,-,rfalSetPostTxRxCallback,void,rfalPostTxRxCallback +Function,-,rfalSetPreTxRxCallback,void,rfalPreTxRxCallback +Function,-,rfalSetUpperLayerCallback,void,rfalUpperLayerCallback +Function,-,rfalSt25tbPollerCheckPresence,ReturnCode,uint8_t* +Function,-,rfalSt25tbPollerCollisionResolution,ReturnCode,"uint8_t, rfalSt25tbListenDevice*, uint8_t*" +Function,-,rfalSt25tbPollerCompletion,ReturnCode, +Function,-,rfalSt25tbPollerGetUID,ReturnCode,rfalSt25tbUID* +Function,-,rfalSt25tbPollerInitialize,ReturnCode, +Function,-,rfalSt25tbPollerInitiate,ReturnCode,uint8_t* +Function,-,rfalSt25tbPollerPcall,ReturnCode,uint8_t* +Function,-,rfalSt25tbPollerReadBlock,ReturnCode,"uint8_t, rfalSt25tbBlock*" +Function,-,rfalSt25tbPollerResetToInventory,ReturnCode, +Function,-,rfalSt25tbPollerSelect,ReturnCode,uint8_t +Function,-,rfalSt25tbPollerSlotMarker,ReturnCode,"uint8_t, uint8_t*" +Function,-,rfalSt25tbPollerWriteBlock,ReturnCode,"uint8_t, const rfalSt25tbBlock*" +Function,-,rfalStartTransceive,ReturnCode,const rfalTransceiveContext* +Function,-,rfalT1TPollerInitialize,ReturnCode, +Function,-,rfalT1TPollerRall,ReturnCode,"const uint8_t*, uint8_t*, uint16_t, uint16_t*" +Function,-,rfalT1TPollerRid,ReturnCode,rfalT1TRidRes* +Function,-,rfalT1TPollerWrite,ReturnCode,"const uint8_t*, uint8_t, uint8_t" +Function,-,rfalTransceiveBitsBlockingTx,ReturnCode,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t" +Function,-,rfalTransceiveBlockingRx,ReturnCode, +Function,-,rfalTransceiveBlockingTx,ReturnCode,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t" +Function,-,rfalTransceiveBlockingTxRx,ReturnCode,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t" +Function,-,rfalWakeUpModeHasWoke,_Bool, +Function,-,rfalWakeUpModeStart,ReturnCode,const rfalWakeUpConfig* +Function,-,rfalWakeUpModeStop,ReturnCode, +Function,+,rfalWorker,void, +Function,-,rfal_platform_spi_acquire,void, +Function,-,rfal_platform_spi_release,void, +Function,-,rfal_set_callback_context,void,void* +Function,-,rfal_set_state_changed_callback,void,RfalStateChangedCallback +Function,-,rindex,char*,"const char*, int" +Function,-,rint,double,double +Function,-,rintf,float,float +Function,-,rintl,long double,long double +Function,-,round,double,double +Function,+,roundf,float,float +Function,-,roundl,long double,long double +Function,+,rpc_session_close,void,RpcSession* +Function,+,rpc_session_feed,size_t,"RpcSession*, uint8_t*, size_t, TickType_t" +Function,+,rpc_session_get_available_size,size_t,RpcSession* +Function,+,rpc_session_open,RpcSession*,Rpc* +Function,+,rpc_session_set_buffer_is_empty_callback,void,"RpcSession*, RpcBufferIsEmptyCallback" +Function,+,rpc_session_set_close_callback,void,"RpcSession*, RpcSessionClosedCallback" +Function,+,rpc_session_set_context,void,"RpcSession*, void*" +Function,+,rpc_session_set_send_bytes_callback,void,"RpcSession*, RpcSendBytesCallback" +Function,+,rpc_session_set_terminated_callback,void,"RpcSession*, RpcSessionTerminatedCallback" +Function,+,rpc_system_app_confirm,void,"RpcAppSystem*, RpcAppSystemEvent, _Bool" +Function,+,rpc_system_app_get_data,const char*,RpcAppSystem* +Function,+,rpc_system_app_send_exited,void,RpcAppSystem* +Function,+,rpc_system_app_send_started,void,RpcAppSystem* +Function,+,rpc_system_app_set_callback,void,"RpcAppSystem*, RpcAppSystemCallback, void*" +Function,-,rpmatch,int,const char* +Function,+,saved_struct_load,_Bool,"const char*, void*, size_t, uint8_t, uint8_t" +Function,+,saved_struct_save,_Bool,"const char*, void*, size_t, uint8_t, uint8_t" +Function,-,scalbln,double,"double, long int" +Function,-,scalblnf,float,"float, long int" +Function,-,scalblnl,long double,"long double, long" +Function,-,scalbn,double,"double, int" +Function,+,scalbnf,float,"float, int" +Function,-,scalbnl,long double,"long double, int" +Function,-,scanf,int,"const char*, ..." +Function,+,scene_manager_alloc,SceneManager*,"const SceneManagerHandlers*, void*" +Function,+,scene_manager_free,void,SceneManager* +Function,+,scene_manager_get_scene_state,uint32_t,"SceneManager*, uint32_t" +Function,+,scene_manager_handle_back_event,_Bool,SceneManager* +Function,+,scene_manager_handle_custom_event,_Bool,"SceneManager*, uint32_t" +Function,+,scene_manager_handle_tick_event,void,SceneManager* +Function,+,scene_manager_has_previous_scene,_Bool,"SceneManager*, uint32_t" +Function,+,scene_manager_next_scene,void,"SceneManager*, uint32_t" +Function,+,scene_manager_previous_scene,_Bool,SceneManager* +Function,+,scene_manager_search_and_switch_to_another_scene,_Bool,"SceneManager*, uint32_t" +Function,+,scene_manager_search_and_switch_to_previous_scene,_Bool,"SceneManager*, uint32_t" +Function,+,scene_manager_search_and_switch_to_previous_scene_one_of,_Bool,"SceneManager*, const uint32_t*, size_t" +Function,+,scene_manager_set_scene_state,void,"SceneManager*, uint32_t, uint32_t" +Function,+,scene_manager_stop,void,SceneManager* +Function,+,sd_api_get_fs_type_text,const char*,SDFsType +Function,-,secure_getenv,char*,const char* +Function,-,seed48,unsigned short*,unsigned short[3] +Function,-,select,int,"int, fd_set*, fd_set*, fd_set*, timeval*" +Function,-,serial_svc_is_started,_Bool, +Function,-,serial_svc_notify_buffer_is_empty,void, +Function,-,serial_svc_set_callbacks,void,"uint16_t, SerialServiceEventCallback, void*" +Function,-,serial_svc_start,void, +Function,-,serial_svc_stop,void, +Function,-,serial_svc_update_tx,_Bool,"uint8_t*, uint16_t" +Function,+,set_random_name,void,"char*, uint8_t" +Function,-,setbuf,void,"FILE*, char*" +Function,-,setbuffer,void,"FILE*, char*, int" +Function,-,setenv,int,"const char*, const char*, int" +Function,-,setkey,void,const char* +Function,-,setlinebuf,int,FILE* +Function,-,setstate,char*,char* +Function,-,setvbuf,int,"FILE*, char*, int, size_t" +Function,+,sha256,void,"const unsigned char*, unsigned int, unsigned char[32]" +Function,+,sha256_finish,void,"sha256_context*, unsigned char[32]" +Function,+,sha256_process,void,sha256_context* +Function,+,sha256_start,void,sha256_context* +Function,+,sha256_update,void,"sha256_context*, const unsigned char*, unsigned int" +Function,-,sin,double,double +Function,-,sincos,void,"double, double*, double*" +Function,-,sincosf,void,"float, float*, float*" +Function,-,sinf,float,float +Function,-,sinh,double,double +Function,-,sinhf,float,float +Function,-,sinhl,long double,long double +Function,-,sinl,long double,long double +Function,-,siprintf,int,"char*, const char*, ..." +Function,-,siscanf,int,"const char*, const char*, ..." +Function,-,sniprintf,int,"char*, size_t, const char*, ..." +Function,+,snprintf,int,"char*, size_t, const char*, ..." +Function,-,sprintf,int,"char*, const char*, ..." +Function,-,sqrt,double,double +Function,-,sqrtf,float,float +Function,-,sqrtl,long double,long double +Function,+,srand,void,unsigned +Function,-,srand48,void,long +Function,-,srandom,void,unsigned +Function,+,sscanf,int,"const char*, const char*, ..." +Function,+,storage_common_copy,FS_Error,"Storage*, const char*, const char*" +Function,+,storage_common_fs_info,FS_Error,"Storage*, const char*, uint64_t*, uint64_t*" +Function,+,storage_common_merge,FS_Error,"Storage*, const char*, const char*" +Function,+,storage_common_mkdir,FS_Error,"Storage*, const char*" +Function,+,storage_common_remove,FS_Error,"Storage*, const char*" +Function,+,storage_common_rename,FS_Error,"Storage*, const char*, const char*" +Function,+,storage_common_stat,FS_Error,"Storage*, const char*, FileInfo*" +Function,+,storage_dir_close,_Bool,File* +Function,+,storage_dir_open,_Bool,"File*, const char*" +Function,+,storage_dir_read,_Bool,"File*, FileInfo*, char*, uint16_t" +Function,-,storage_dir_rewind,_Bool,File* +Function,+,storage_error_get_desc,const char*,FS_Error +Function,+,storage_file_alloc,File*,Storage* +Function,+,storage_file_close,_Bool,File* +Function,+,storage_file_eof,_Bool,File* +Function,+,storage_file_exists,_Bool,"Storage*, const char*" +Function,+,storage_file_free,void,File* +Function,+,storage_file_get_error,FS_Error,File* +Function,+,storage_file_get_error_desc,const char*,File* +Function,-,storage_file_get_internal_error,int32_t,File* +Function,+,storage_file_is_dir,_Bool,File* +Function,+,storage_file_is_open,_Bool,File* +Function,+,storage_file_open,_Bool,"File*, const char*, FS_AccessMode, FS_OpenMode" +Function,+,storage_file_read,uint16_t,"File*, void*, uint16_t" +Function,+,storage_file_seek,_Bool,"File*, uint32_t, _Bool" +Function,+,storage_file_size,uint64_t,File* +Function,-,storage_file_sync,_Bool,File* +Function,+,storage_file_tell,uint64_t,File* +Function,+,storage_file_truncate,_Bool,File* +Function,+,storage_file_write,uint16_t,"File*, const void*, uint16_t" +Function,+,storage_get_next_filename,void,"Storage*, const char*, const char*, const char*, string_t, uint8_t" +Function,+,storage_get_pubsub,FuriPubSub*,Storage* +Function,+,storage_int_backup,FS_Error,"Storage*, const char*" +Function,+,storage_int_restore,FS_Error,"Storage*, const char*, Storage_name_converter" +Function,+,storage_sd_format,FS_Error,Storage* +Function,+,storage_sd_info,FS_Error,"Storage*, SDInfo*" +Function,+,storage_sd_status,FS_Error,Storage* +Function,+,storage_sd_unmount,FS_Error,Storage* +Function,+,storage_simply_mkdir,_Bool,"Storage*, const char*" +Function,+,storage_simply_remove,_Bool,"Storage*, const char*" +Function,+,storage_simply_remove_recursive,_Bool,"Storage*, const char*" +Function,-,stpcpy,char*,"char*, const char*" +Function,-,stpncpy,char*,"char*, const char*, size_t" +Function,-,strcasecmp,int,"const char*, const char*" +Function,-,strcasecmp_l,int,"const char*, const char*, locale_t" +Function,+,strcasestr,char*,"const char*, const char*" +Function,-,strcat,char*,"char*, const char*" +Function,+,strchr,char*,"const char*, int" +Function,-,strchrnul,char*,"const char*, int" +Function,+,strcmp,int,"const char*, const char*" +Function,-,strcoll,int,"const char*, const char*" +Function,-,strcoll_l,int,"const char*, const char*, locale_t" +Function,+,strcpy,char*,"char*, const char*" +Function,+,strcspn,size_t,"const char*, const char*" +Function,+,strdup,char*,const char* +Function,+,stream_clean,void,Stream* +Function,+,stream_copy,size_t,"Stream*, Stream*, size_t" +Function,+,stream_copy_full,size_t,"Stream*, Stream*" +Function,+,stream_delete,_Bool,"Stream*, size_t" +Function,+,stream_delete_and_insert,_Bool,"Stream*, size_t, StreamWriteCB, const void*" +Function,+,stream_delete_and_insert_char,_Bool,"Stream*, size_t, char" +Function,+,stream_delete_and_insert_cstring,_Bool,"Stream*, size_t, const char*" +Function,+,stream_delete_and_insert_format,_Bool,"Stream*, size_t, const char*, ..." +Function,+,stream_delete_and_insert_string,_Bool,"Stream*, size_t, string_t" +Function,+,stream_delete_and_insert_vaformat,_Bool,"Stream*, size_t, const char*, va_list" +Function,+,stream_dump_data,void,Stream* +Function,+,stream_eof,_Bool,Stream* +Function,+,stream_free,void,Stream* +Function,+,stream_insert,_Bool,"Stream*, const uint8_t*, size_t" +Function,+,stream_insert_char,_Bool,"Stream*, char" +Function,+,stream_insert_cstring,_Bool,"Stream*, const char*" +Function,+,stream_insert_format,_Bool,"Stream*, const char*, ..." +Function,+,stream_insert_string,_Bool,"Stream*, string_t" +Function,+,stream_insert_vaformat,_Bool,"Stream*, const char*, va_list" +Function,+,stream_load_from_file,size_t,"Stream*, Storage*, const char*" +Function,+,stream_read,size_t,"Stream*, uint8_t*, size_t" +Function,+,stream_read_line,_Bool,"Stream*, string_t" +Function,+,stream_rewind,_Bool,Stream* +Function,+,stream_save_to_file,size_t,"Stream*, Storage*, const char*, FS_OpenMode" +Function,+,stream_seek,_Bool,"Stream*, int32_t, StreamOffset" +Function,+,stream_size,size_t,Stream* +Function,+,stream_split,_Bool,"Stream*, Stream*, Stream*" +Function,+,stream_tell,size_t,Stream* +Function,+,stream_write,size_t,"Stream*, const uint8_t*, size_t" +Function,+,stream_write_char,size_t,"Stream*, char" +Function,+,stream_write_cstring,size_t,"Stream*, const char*" +Function,+,stream_write_format,size_t,"Stream*, const char*, ..." +Function,+,stream_write_string,size_t,"Stream*, string_t" +Function,+,stream_write_vaformat,size_t,"Stream*, const char*, va_list" +Function,-,strerror,char*,int +Function,-,strerror_l,char*,"int, locale_t" +Function,-,strerror_r,char*,"int, char*, size_t" +Function,+,string_stream_alloc,Stream*, +Function,-,strlcat,size_t,"char*, const char*, size_t" +Function,+,strlcpy,size_t,"char*, const char*, size_t" +Function,+,strlen,size_t,const char* +Function,-,strlwr,char*,char* +Function,+,strncasecmp,int,"const char*, const char*, size_t" +Function,-,strncasecmp_l,int,"const char*, const char*, size_t, locale_t" +Function,-,strncat,char*,"char*, const char*, size_t" +Function,+,strncmp,int,"const char*, const char*, size_t" +Function,+,strncpy,char*,"char*, const char*, size_t" +Function,-,strndup,char*,"const char*, size_t" +Function,-,strnlen,size_t,"const char*, size_t" +Function,-,strnstr,char*,"const char*, const char*, size_t" +Function,-,strpbrk,char*,"const char*, const char*" +Function,+,strrchr,char*,"const char*, int" +Function,-,strsep,char*,"char**, const char*" +Function,-,strsignal,char*,int +Function,+,strspn,size_t,"const char*, const char*" +Function,+,strstr,char*,"const char*, const char*" +Function,-,strtod,double,"const char*, char**" +Function,-,strtod_l,double,"const char*, char**, locale_t" +Function,+,strtof,float,"const char*, char**" +Function,-,strtof_l,float,"const char*, char**, locale_t" +Function,-,strtok,char*,"char*, const char*" +Function,-,strtok_r,char*,"char*, const char*, char**" +Function,+,strtol,long,"const char*, char**, int" +Function,-,strtol_l,long,"const char*, char**, int, locale_t" +Function,-,strtold,long double,"const char*, char**" +Function,-,strtold_l,long double,"const char*, char**, locale_t" +Function,-,strtoll,long long,"const char*, char**, int" +Function,-,strtoll_l,long long,"const char*, char**, int, locale_t" +Function,+,strtoul,unsigned long,"const char*, char**, int" +Function,-,strtoul_l,unsigned long,"const char*, char**, int, locale_t" +Function,+,strtoull,unsigned long long,"const char*, char**, int" +Function,-,strtoull_l,unsigned long long,"const char*, char**, int, locale_t" +Function,-,strupr,char*,char* +Function,-,strverscmp,int,"const char*, const char*" +Function,-,strxfrm,size_t,"char*, const char*, size_t" +Function,-,strxfrm_l,size_t,"char*, const char*, size_t, locale_t" +Function,+,subghz_environment_alloc,SubGhzEnvironment*, +Function,+,subghz_environment_free,void,SubGhzEnvironment* +Function,-,subghz_environment_get_came_atomo_rainbow_table_file_name,const char*,SubGhzEnvironment* +Function,-,subghz_environment_get_keystore,SubGhzKeystore*,SubGhzEnvironment* +Function,-,subghz_environment_get_nice_flor_s_rainbow_table_file_name,const char*,SubGhzEnvironment* +Function,+,subghz_environment_load_keystore,_Bool,"SubGhzEnvironment*, const char*" +Function,-,subghz_environment_set_came_atomo_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*" +Function,-,subghz_environment_set_nice_flor_s_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*" +Function,-,subghz_keystore_alloc,SubGhzKeystore*, +Function,-,subghz_keystore_free,void,SubGhzKeystore* +Function,-,subghz_keystore_get_data,SubGhzKeyArray_t*,SubGhzKeystore* +Function,-,subghz_keystore_load,_Bool,"SubGhzKeystore*, const char*" +Function,-,subghz_keystore_raw_encrypted_save,_Bool,"const char*, const char*, uint8_t*" +Function,-,subghz_keystore_raw_get_data,_Bool,"const char*, size_t, uint8_t*, size_t" +Function,-,subghz_keystore_save,_Bool,"SubGhzKeystore*, const char*, uint8_t*" +Function,-,subghz_protocol_decoder_base_deserialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*" +Function,-,subghz_protocol_decoder_base_get_hash_data,uint8_t,SubGhzProtocolDecoderBase* +Function,-,subghz_protocol_decoder_base_get_string,_Bool,"SubGhzProtocolDecoderBase*, string_t" +Function,+,subghz_protocol_decoder_base_serialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*, SubGhzPresetDefinition*" +Function,-,subghz_protocol_decoder_base_set_decoder_callback,void,"SubGhzProtocolDecoderBase*, SubGhzProtocolDecoderBaseRxCallback, void*" +Function,+,subghz_protocol_decoder_raw_alloc,void*,SubGhzEnvironment* +Function,+,subghz_protocol_decoder_raw_deserialize,_Bool,"void*, FlipperFormat*" +Function,+,subghz_protocol_decoder_raw_feed,void,"void*, _Bool, uint32_t" +Function,+,subghz_protocol_decoder_raw_free,void,void* +Function,+,subghz_protocol_decoder_raw_get_string,void,"void*, string_t" +Function,+,subghz_protocol_decoder_raw_reset,void,void* +Function,+,subghz_protocol_encoder_raw_alloc,void*,SubGhzEnvironment* +Function,+,subghz_protocol_encoder_raw_deserialize,_Bool,"void*, FlipperFormat*" +Function,+,subghz_protocol_encoder_raw_free,void,void* +Function,+,subghz_protocol_encoder_raw_stop,void,void* +Function,+,subghz_protocol_encoder_raw_yield,LevelDuration,void* +Function,+,subghz_protocol_raw_file_encoder_worker_set_callback_end,void,"SubGhzProtocolEncoderRAW*, SubGhzProtocolEncoderRAWCallbackEnd, void*" +Function,+,subghz_protocol_raw_gen_fff_data,void,"FlipperFormat*, const char*" +Function,+,subghz_protocol_raw_get_sample_write,size_t,SubGhzProtocolDecoderRAW* +Function,+,subghz_protocol_raw_save_to_file_init,_Bool,"SubGhzProtocolDecoderRAW*, const char*, SubGhzPresetDefinition*" +Function,+,subghz_protocol_raw_save_to_file_stop,void,SubGhzProtocolDecoderRAW* +Function,+,subghz_receiver_alloc_init,SubGhzReceiver*,SubGhzEnvironment* +Function,+,subghz_receiver_decode,void,"SubGhzReceiver*, _Bool, uint32_t" +Function,+,subghz_receiver_free,void,SubGhzReceiver* +Function,+,subghz_receiver_reset,void,SubGhzReceiver* +Function,+,subghz_receiver_search_decoder_base_by_name,SubGhzProtocolDecoderBase*,"SubGhzReceiver*, const char*" +Function,+,subghz_receiver_set_filter,void,"SubGhzReceiver*, SubGhzProtocolFlag" +Function,+,subghz_receiver_set_rx_callback,void,"SubGhzReceiver*, SubGhzReceiverCallback, void*" +Function,+,subghz_transmitter_alloc_init,SubGhzTransmitter*,"SubGhzEnvironment*, const char*" +Function,+,subghz_transmitter_deserialize,_Bool,"SubGhzTransmitter*, FlipperFormat*" +Function,+,subghz_transmitter_free,void,SubGhzTransmitter* +Function,+,subghz_transmitter_get_protocol_instance,SubGhzProtocolEncoderBase*,SubGhzTransmitter* +Function,+,subghz_transmitter_stop,_Bool,SubGhzTransmitter* +Function,+,subghz_transmitter_yield,LevelDuration,void* +Function,+,subghz_tx_rx_worker_alloc,SubGhzTxRxWorker*, +Function,+,subghz_tx_rx_worker_available,size_t,SubGhzTxRxWorker* +Function,+,subghz_tx_rx_worker_free,void,SubGhzTxRxWorker* +Function,+,subghz_tx_rx_worker_is_running,_Bool,SubGhzTxRxWorker* +Function,+,subghz_tx_rx_worker_read,size_t,"SubGhzTxRxWorker*, uint8_t*, size_t" +Function,+,subghz_tx_rx_worker_set_callback_have_read,void,"SubGhzTxRxWorker*, SubGhzTxRxWorkerCallbackHaveRead, void*" +Function,+,subghz_tx_rx_worker_start,_Bool,"SubGhzTxRxWorker*, uint32_t" +Function,+,subghz_tx_rx_worker_stop,void,SubGhzTxRxWorker* +Function,+,subghz_tx_rx_worker_write,_Bool,"SubGhzTxRxWorker*, uint8_t*, size_t" +Function,+,subghz_worker_alloc,SubGhzWorker*, +Function,+,subghz_worker_free,void,SubGhzWorker* +Function,+,subghz_worker_is_running,_Bool,SubGhzWorker* +Function,+,subghz_worker_rx_callback,void,"_Bool, uint32_t, void*" +Function,+,subghz_worker_set_context,void,"SubGhzWorker*, void*" +Function,+,subghz_worker_set_overrun_callback,void,"SubGhzWorker*, SubGhzWorkerOverrunCallback" +Function,+,subghz_worker_set_pair_callback,void,"SubGhzWorker*, SubGhzWorkerPairCallback" +Function,+,subghz_worker_start,void,SubGhzWorker* +Function,+,subghz_worker_stop,void,SubGhzWorker* +Function,+,submenu_add_item,void,"Submenu*, const char*, uint32_t, SubmenuItemCallback, void*" +Function,+,submenu_alloc,Submenu*, +Function,+,submenu_free,void,Submenu* +Function,+,submenu_get_view,View*,Submenu* +Function,+,submenu_reset,void,Submenu* +Function,+,submenu_set_header,void,"Submenu*, const char*" +Function,+,submenu_set_selected_item,void,"Submenu*, uint32_t" +Function,-,system,int,const char* +Function,+,t5577_write,void,LFRFIDT5577* +Function,-,tan,double,double +Function,-,tanf,float,float +Function,-,tanh,double,double +Function,-,tanhf,float,float +Function,-,tanhl,long double,long double +Function,-,tanl,long double,long double +Function,+,tar_archive_add_dir,_Bool,"TarArchive*, const char*, const char*" +Function,+,tar_archive_add_file,_Bool,"TarArchive*, const char*, const char*, const int32_t" +Function,+,tar_archive_alloc,TarArchive*,Storage* +Function,+,tar_archive_dir_add_element,_Bool,"TarArchive*, const char*" +Function,+,tar_archive_file_add_data_block,_Bool,"TarArchive*, const uint8_t*, const int32_t" +Function,+,tar_archive_file_add_header,_Bool,"TarArchive*, const char*, const int32_t" +Function,+,tar_archive_file_finalize,_Bool,TarArchive* +Function,+,tar_archive_finalize,_Bool,TarArchive* +Function,+,tar_archive_free,void,TarArchive* +Function,+,tar_archive_get_entries_count,int32_t,TarArchive* +Function,+,tar_archive_open,_Bool,"TarArchive*, const char*, TarOpenMode" +Function,+,tar_archive_set_file_callback,void,"TarArchive*, tar_unpack_file_cb, void*" +Function,+,tar_archive_store_data,_Bool,"TarArchive*, const char*, const uint8_t*, const int32_t" +Function,+,tar_archive_unpack_to,_Bool,"TarArchive*, const char*, Storage_name_converter" +Function,-,tempnam,char*,"const char*, const char*" +Function,+,text_box_alloc,TextBox*, +Function,+,text_box_free,void,TextBox* +Function,+,text_box_get_view,View*,TextBox* +Function,+,text_box_reset,void,TextBox* +Function,+,text_box_set_focus,void,"TextBox*, TextBoxFocus" +Function,+,text_box_set_font,void,"TextBox*, TextBoxFont" +Function,+,text_box_set_text,void,"TextBox*, const char*" +Function,+,text_input_alloc,TextInput*, +Function,+,text_input_free,void,TextInput* +Function,+,text_input_get_validator_callback,TextInputValidatorCallback,TextInput* +Function,+,text_input_get_validator_callback_context,void*,TextInput* +Function,+,text_input_get_view,View*,TextInput* +Function,+,text_input_reset,void,TextInput* +Function,+,text_input_set_header_text,void,"TextInput*, const char*" +Function,+,text_input_set_result_callback,void,"TextInput*, TextInputCallback, void*, char*, size_t, _Bool" +Function,+,text_input_set_validator,void,"TextInput*, TextInputValidatorCallback, void*" +Function,-,tgamma,double,double +Function,-,tgammaf,float,float +Function,-,tgammal,long double,long double +Function,+,timerCalculateTimer,uint32_t,uint16_t +Function,-,timerDelay,void,uint16_t +Function,+,timerIsExpired,_Bool,uint32_t +Function,-,timerStopwatchMeasure,uint32_t, +Function,-,timerStopwatchStart,void, +Function,-,timingsafe_bcmp,int,"const void*, const void*, size_t" +Function,-,timingsafe_memcmp,int,"const void*, const void*, size_t" +Function,-,tmpfile,FILE*, +Function,-,tmpnam,char*,char* +Function,-,toascii,int,int +Function,-,toascii_l,int,"int, locale_t" +Function,-,tolower,int,int +Function,-,tolower_l,int,"int, locale_t" +Function,-,toupper,int,int +Function,-,toupper_l,int,"int, locale_t" +Function,-,trunc,double,double +Function,-,truncf,float,float +Function,-,truncl,long double,long double +Function,-,uECC_compress,void,"const uint8_t*, uint8_t*, uECC_Curve" +Function,+,uECC_compute_public_key,int,"const uint8_t*, uint8_t*, uECC_Curve" +Function,-,uECC_curve_private_key_size,int,uECC_Curve +Function,-,uECC_curve_public_key_size,int,uECC_Curve +Function,-,uECC_decompress,void,"const uint8_t*, uint8_t*, uECC_Curve" +Function,-,uECC_get_rng,uECC_RNG_Function, +Function,-,uECC_make_key,int,"uint8_t*, uint8_t*, uECC_Curve" +Function,-,uECC_secp160r1,uECC_Curve, +Function,-,uECC_secp192r1,uECC_Curve, +Function,-,uECC_secp224r1,uECC_Curve, +Function,-,uECC_secp256k1,uECC_Curve, +Function,+,uECC_secp256r1,uECC_Curve, +Function,+,uECC_set_rng,void,uECC_RNG_Function +Function,-,uECC_shared_secret,int,"const uint8_t*, const uint8_t*, uint8_t*, uECC_Curve" +Function,+,uECC_sign,int,"const uint8_t*, const uint8_t*, unsigned, uint8_t*, uECC_Curve" +Function,-,uECC_sign_deterministic,int,"const uint8_t*, const uint8_t*, unsigned, const uECC_HashContext*, uint8_t*, uECC_Curve" +Function,-,uECC_valid_public_key,int,"const uint8_t*, uECC_Curve" +Function,-,uECC_verify,int,"const uint8_t*, const uint8_t*, unsigned, const uint8_t*, uECC_Curve" +Function,-,ulTaskGenericNotifyTake,uint32_t,"UBaseType_t, BaseType_t, TickType_t" +Function,-,ulTaskGenericNotifyValueClear,uint32_t,"TaskHandle_t, UBaseType_t, uint32_t" +Function,-,ulTaskGetIdleRunTimeCounter,uint32_t, +Function,-,ulTaskGetIdleRunTimePercent,uint32_t, +Function,-,ungetc,int,"int, FILE*" +Function,-,unsetenv,int,const char* +Function,-,usbd_poll,void,usbd_device* +Function,-,utoa,char*,"unsigned, char*, int" +Function,-,uxListRemove,UBaseType_t,ListItem_t* +Function,-,uxTaskGetNumberOfTasks,UBaseType_t, +Function,-,uxTaskGetStackHighWaterMark,UBaseType_t,TaskHandle_t +Function,-,uxTaskGetStackHighWaterMark2,uint16_t,TaskHandle_t +Function,-,uxTaskGetSystemState,UBaseType_t,"TaskStatus_t*, const UBaseType_t, uint32_t*" +Function,-,uxTaskGetTaskNumber,UBaseType_t,TaskHandle_t +Function,-,uxTaskPriorityGet,UBaseType_t,const TaskHandle_t +Function,-,uxTaskPriorityGetFromISR,UBaseType_t,const TaskHandle_t +Function,-,uxTaskResetEventItemValue,TickType_t, +Function,-,uxTimerGetReloadMode,UBaseType_t,TimerHandle_t +Function,-,uxTimerGetTimerNumber,UBaseType_t,TimerHandle_t +Function,-,vApplicationGetIdleTaskMemory,void,"StaticTask_t**, StackType_t**, uint32_t*" +Function,-,vApplicationGetTimerTaskMemory,void,"StaticTask_t**, StackType_t**, uint32_t*" +Function,-,vListInitialise,void,List_t* +Function,-,vListInitialiseItem,void,ListItem_t* +Function,-,vListInsert,void,"List_t*, ListItem_t*" +Function,-,vListInsertEnd,void,"List_t*, ListItem_t*" +Function,-,vPortDefineHeapRegions,void,const HeapRegion_t* +Function,-,vPortEndScheduler,void, +Function,+,vPortEnterCritical,void, +Function,+,vPortExitCritical,void, +Function,-,vPortFree,void,void* +Function,-,vPortGetHeapStats,void,HeapStats_t* +Function,-,vPortInitialiseBlocks,void, +Function,-,vPortSuppressTicksAndSleep,void,TickType_t +Function,-,vTaskAllocateMPURegions,void,"TaskHandle_t, const MemoryRegion_t*" +Function,-,vTaskDelay,void,const TickType_t +Function,-,vTaskDelete,void,TaskHandle_t +Function,-,vTaskEndScheduler,void, +Function,-,vTaskGenericNotifyGiveFromISR,void,"TaskHandle_t, UBaseType_t, BaseType_t*" +Function,-,vTaskGetInfo,void,"TaskHandle_t, TaskStatus_t*, BaseType_t, eTaskState" +Function,-,vTaskGetRunTimeStats,void,char* +Function,-,vTaskInternalSetTimeOutState,void,TimeOut_t* +Function,-,vTaskList,void,char* +Function,-,vTaskMissedYield,void, +Function,-,vTaskPlaceOnEventList,void,"List_t*, const TickType_t" +Function,-,vTaskPlaceOnEventListRestricted,void,"List_t*, TickType_t, const BaseType_t" +Function,-,vTaskPlaceOnUnorderedEventList,void,"List_t*, const TickType_t, const TickType_t" +Function,-,vTaskPriorityDisinheritAfterTimeout,void,"const TaskHandle_t, UBaseType_t" +Function,+,vTaskPrioritySet,void,"TaskHandle_t, UBaseType_t" +Function,-,vTaskRemoveFromUnorderedEventList,void,"ListItem_t*, const TickType_t" +Function,-,vTaskResume,void,TaskHandle_t +Function,-,vTaskSetTaskNumber,void,"TaskHandle_t, const UBaseType_t" +Function,-,vTaskSetThreadLocalStoragePointer,void,"TaskHandle_t, BaseType_t, void*" +Function,-,vTaskSetTimeOutState,void,TimeOut_t* +Function,-,vTaskStartScheduler,void, +Function,-,vTaskStepTick,void,const TickType_t +Function,-,vTaskSuspend,void,TaskHandle_t +Function,-,vTaskSuspendAll,void, +Function,-,vTaskSwitchContext,void, +Function,-,vTimerSetReloadMode,void,"TimerHandle_t, const UBaseType_t" +Function,-,vTimerSetTimerID,void,"TimerHandle_t, void*" +Function,-,vTimerSetTimerNumber,void,"TimerHandle_t, UBaseType_t" +Function,+,validator_is_file_alloc_init,ValidatorIsFile*,"const char*, const char*, const char*" +Function,+,validator_is_file_callback,_Bool,"const char*, string_t, void*" +Function,+,validator_is_file_free,void,ValidatorIsFile* +Function,+,variable_item_get_context,void*,VariableItem* +Function,+,variable_item_get_current_value_index,uint8_t,VariableItem* +Function,+,variable_item_list_add,VariableItem*,"VariableItemList*, const char*, uint8_t, VariableItemChangeCallback, void*" +Function,+,variable_item_list_alloc,VariableItemList*, +Function,+,variable_item_list_free,void,VariableItemList* +Function,+,variable_item_list_get_selected_item_index,uint8_t,VariableItemList* +Function,+,variable_item_list_get_view,View*,VariableItemList* +Function,+,variable_item_list_reset,void,VariableItemList* +Function,+,variable_item_list_set_enter_callback,void,"VariableItemList*, VariableItemListEnterCallback, void*" +Function,+,variable_item_list_set_selected_item,void,"VariableItemList*, uint8_t" +Function,+,variable_item_set_current_value_index,void,"VariableItem*, uint8_t" +Function,+,variable_item_set_current_value_text,void,"VariableItem*, const char*" +Function,-,vasiprintf,int,"char**, const char*, __gnuc_va_list" +Function,-,vasniprintf,char*,"char*, size_t*, const char*, __gnuc_va_list" +Function,-,vasnprintf,char*,"char*, size_t*, const char*, __gnuc_va_list" +Function,-,vasprintf,int,"char**, const char*, __gnuc_va_list" +Function,-,vdiprintf,int,"int, const char*, __gnuc_va_list" +Function,-,vdprintf,int,"int, const char*, __gnuc_va_list" +Function,+,version_get,const Version*, +Function,+,version_get_builddate,const char*,const Version* +Function,+,version_get_dirty_flag,_Bool,const Version* +Function,+,version_get_gitbranch,const char*,const Version* +Function,+,version_get_gitbranchnum,const char*,const Version* +Function,+,version_get_githash,const char*,const Version* +Function,+,version_get_target,uint8_t,const Version* +Function,+,version_get_version,const char*,const Version* +Function,-,vfiprintf,int,"FILE*, const char*, __gnuc_va_list" +Function,-,vfiscanf,int,"FILE*, const char*, __gnuc_va_list" +Function,-,vfprintf,int,"FILE*, const char*, __gnuc_va_list" +Function,-,vfscanf,int,"FILE*, const char*, __gnuc_va_list" +Function,+,view_alloc,View*, +Function,+,view_allocate_model,void,"View*, ViewModelType, size_t" +Function,+,view_commit_model,void,"View*, _Bool" +Function,+,view_dispatcher_add_view,void,"ViewDispatcher*, uint32_t, View*" +Function,+,view_dispatcher_alloc,ViewDispatcher*, +Function,+,view_dispatcher_attach_to_gui,void,"ViewDispatcher*, Gui*, ViewDispatcherType" +Function,+,view_dispatcher_enable_queue,void,ViewDispatcher* +Function,+,view_dispatcher_free,void,ViewDispatcher* +Function,+,view_dispatcher_remove_view,void,"ViewDispatcher*, uint32_t" +Function,+,view_dispatcher_run,void,ViewDispatcher* +Function,+,view_dispatcher_send_custom_event,void,"ViewDispatcher*, uint32_t" +Function,+,view_dispatcher_send_to_back,void,ViewDispatcher* +Function,+,view_dispatcher_send_to_front,void,ViewDispatcher* +Function,+,view_dispatcher_set_custom_event_callback,void,"ViewDispatcher*, ViewDispatcherCustomEventCallback" +Function,+,view_dispatcher_set_event_callback_context,void,"ViewDispatcher*, void*" +Function,+,view_dispatcher_set_navigation_event_callback,void,"ViewDispatcher*, ViewDispatcherNavigationEventCallback" +Function,+,view_dispatcher_set_tick_event_callback,void,"ViewDispatcher*, ViewDispatcherTickEventCallback, uint32_t" +Function,+,view_dispatcher_stop,void,ViewDispatcher* +Function,+,view_dispatcher_switch_to_view,void,"ViewDispatcher*, uint32_t" +Function,+,view_free,void,View* +Function,+,view_free_model,void,View* +Function,+,view_get_model,void*,View* +Function,+,view_port_alloc,ViewPort*, +Function,+,view_port_draw_callback_set,void,"ViewPort*, ViewPortDrawCallback, void*" +Function,+,view_port_enabled_set,void,"ViewPort*, _Bool" +Function,+,view_port_free,void,ViewPort* +Function,-,view_port_get_height,uint8_t,ViewPort* +Function,+,view_port_get_orientation,ViewPortOrientation,const ViewPort* +Function,+,view_port_get_width,uint8_t,ViewPort* +Function,+,view_port_input_callback_set,void,"ViewPort*, ViewPortInputCallback, void*" +Function,+,view_port_is_enabled,_Bool,ViewPort* +Function,-,view_port_set_height,void,"ViewPort*, uint8_t" +Function,+,view_port_set_orientation,void,"ViewPort*, ViewPortOrientation" +Function,+,view_port_set_width,void,"ViewPort*, uint8_t" +Function,+,view_port_update,void,ViewPort* +Function,+,view_set_context,void,"View*, void*" +Function,-,view_set_custom_callback,void,"View*, ViewCustomCallback" +Function,+,view_set_draw_callback,void,"View*, ViewDrawCallback" +Function,+,view_set_enter_callback,void,"View*, ViewCallback" +Function,+,view_set_exit_callback,void,"View*, ViewCallback" +Function,+,view_set_input_callback,void,"View*, ViewInputCallback" +Function,+,view_set_orientation,void,"View*, ViewOrientation" +Function,+,view_set_previous_callback,void,"View*, ViewNavigationCallback" +Function,+,view_set_update_callback,void,"View*, ViewUpdateCallback" +Function,+,view_set_update_callback_context,void,"View*, void*" +Function,+,view_stack_add_view,void,"ViewStack*, View*" +Function,+,view_stack_alloc,ViewStack*, +Function,+,view_stack_free,void,ViewStack* +Function,+,view_stack_get_view,View*,ViewStack* +Function,+,view_stack_remove_view,void,"ViewStack*, View*" +Function,+,view_tie_icon_animation,void,"View*, IconAnimation*" +Function,-,viprintf,int,"const char*, __gnuc_va_list" +Function,-,viscanf,int,"const char*, __gnuc_va_list" +Function,-,vprintf,int,"const char*, __gnuc_va_list" +Function,-,vscanf,int,"const char*, __gnuc_va_list" +Function,-,vsiprintf,int,"char*, const char*, __gnuc_va_list" +Function,-,vsiscanf,int,"const char*, const char*, __gnuc_va_list" +Function,-,vsniprintf,int,"char*, size_t, const char*, __gnuc_va_list" +Function,-,vsnprintf,int,"char*, size_t, const char*, __gnuc_va_list" +Function,-,vsprintf,int,"char*, const char*, __gnuc_va_list" +Function,-,vsscanf,int,"const char*, const char*, __gnuc_va_list" +Function,-,wcstombs,size_t,"char*, const wchar_t*, size_t" +Function,-,wctomb,int,"char*, wchar_t" +Function,+,widget_add_button_element,void,"Widget*, GuiButtonType, const char*, ButtonCallback, void*" +Function,+,widget_add_frame_element,void,"Widget*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t" +Function,+,widget_add_icon_element,void,"Widget*, uint8_t, uint8_t, const Icon*" +Function,+,widget_add_string_element,void,"Widget*, uint8_t, uint8_t, Align, Align, Font, const char*" +Function,+,widget_add_string_multiline_element,void,"Widget*, uint8_t, uint8_t, Align, Align, Font, const char*" +Function,+,widget_add_text_box_element,void,"Widget*, uint8_t, uint8_t, uint8_t, uint8_t, Align, Align, const char*, _Bool" +Function,+,widget_add_text_scroll_element,void,"Widget*, uint8_t, uint8_t, uint8_t, uint8_t, const char*" +Function,+,widget_alloc,Widget*, +Function,+,widget_free,void,Widget* +Function,+,widget_get_view,View*,Widget* +Function,+,widget_reset,void,Widget* +Function,-,write_mutex,_Bool,"ValueMutex*, void*, size_t, uint32_t" +Function,-,xPortGetFreeHeapSize,size_t, +Function,-,xPortGetMinimumEverFreeHeapSize,size_t, +Function,-,xPortStartScheduler,BaseType_t, +Function,-,xTaskAbortDelay,BaseType_t,TaskHandle_t +Function,-,xTaskCallApplicationTaskHook,BaseType_t,"TaskHandle_t, void*" +Function,-,xTaskCatchUpTicks,BaseType_t,TickType_t +Function,-,xTaskCheckForTimeOut,BaseType_t,"TimeOut_t*, TickType_t*" +Function,-,xTaskCreate,BaseType_t,"TaskFunction_t, const char*, const uint16_t, void*, UBaseType_t, TaskHandle_t*" +Function,-,xTaskCreateStatic,TaskHandle_t,"TaskFunction_t, const char*, const uint32_t, void*, UBaseType_t, StackType_t*, StaticTask_t*" +Function,-,xTaskDelayUntil,BaseType_t,"TickType_t*, const TickType_t" +Function,-,xTaskGenericNotify,BaseType_t,"TaskHandle_t, UBaseType_t, uint32_t, eNotifyAction, uint32_t*" +Function,-,xTaskGenericNotifyFromISR,BaseType_t,"TaskHandle_t, UBaseType_t, uint32_t, eNotifyAction, uint32_t*, BaseType_t*" +Function,-,xTaskGenericNotifyStateClear,BaseType_t,"TaskHandle_t, UBaseType_t" +Function,-,xTaskGenericNotifyWait,BaseType_t,"UBaseType_t, uint32_t, uint32_t, uint32_t*, TickType_t" +Function,-,xTaskGetCurrentTaskHandle,TaskHandle_t, +Function,+,xTaskGetHandle,TaskHandle_t,const char* +Function,-,xTaskGetIdleTaskHandle,TaskHandle_t, +Function,+,xTaskGetSchedulerState,BaseType_t, +Function,+,xTaskGetTickCount,TickType_t, +Function,-,xTaskGetTickCountFromISR,TickType_t, +Function,-,xTaskIncrementTick,BaseType_t, +Function,-,xTaskPriorityDisinherit,BaseType_t,const TaskHandle_t +Function,-,xTaskPriorityInherit,BaseType_t,const TaskHandle_t +Function,-,xTaskRemoveFromEventList,BaseType_t,const List_t* +Function,-,xTaskResumeAll,BaseType_t, +Function,-,xTaskResumeFromISR,BaseType_t,TaskHandle_t +Function,-,xTimerCreate,TimerHandle_t,"const char*, const TickType_t, const UBaseType_t, void*, TimerCallbackFunction_t" +Function,-,xTimerCreateStatic,TimerHandle_t,"const char*, const TickType_t, const UBaseType_t, void*, TimerCallbackFunction_t, StaticTimer_t*" +Function,-,xTimerCreateTimerTask,BaseType_t, +Function,-,xTimerGenericCommand,BaseType_t,"TimerHandle_t, const BaseType_t, const TickType_t, BaseType_t*, const TickType_t" +Function,-,xTimerGetExpiryTime,TickType_t,TimerHandle_t +Function,-,xTimerGetPeriod,TickType_t,TimerHandle_t +Function,-,xTimerGetTimerDaemonTaskHandle,TaskHandle_t, +Function,-,xTimerIsTimerActive,BaseType_t,TimerHandle_t +Function,-,xTimerPendFunctionCall,BaseType_t,"PendedFunction_t, void*, uint32_t, TickType_t" +Function,-,xTimerPendFunctionCallFromISR,BaseType_t,"PendedFunction_t, void*, uint32_t, BaseType_t*" +Function,-,y0,double,double +Function,-,y0f,float,float +Function,-,y1,double,double +Function,-,y1f,float,float +Function,-,yn,double,"int, double" +Function,-,ynf,float,"int, float" +Variable,-,AHBPrescTable,const uint32_t[16], +Variable,-,APBPrescTable,const uint32_t[8], +Variable,+,A_125khz_14,const Icon, +Variable,+,A_BadUsb_14,const Icon, +Variable,+,A_Debug_14,const Icon, +Variable,+,A_FileManager_14,const Icon, +Variable,+,A_GPIO_14,const Icon, +Variable,+,A_Infrared_14,const Icon, +Variable,+,A_Levelup1_128x64,const Icon, +Variable,+,A_Levelup2_128x64,const Icon, +Variable,+,A_Loading_24,const Icon, +Variable,+,A_NFC_14,const Icon, +Variable,+,A_Plugins_14,const Icon, +Variable,+,A_Round_loader_8x8,const Icon, +Variable,+,A_Settings_14,const Icon, +Variable,+,A_Sub1ghz_14,const Icon, +Variable,+,A_U2F_14,const Icon, +Variable,+,A_iButton_14,const Icon, +Variable,-,ITM_RxBuffer,volatile int32_t, +Variable,+,I_125_10px,const Icon, +Variable,+,I_ActiveConnection_50x64,const Icon, +Variable,+,I_ArrowC_1_36x36,const Icon, +Variable,+,I_ArrowDownEmpty_14x15,const Icon, +Variable,+,I_ArrowDownFilled_14x15,const Icon, +Variable,+,I_ArrowUpEmpty_14x15,const Icon, +Variable,+,I_ArrowUpFilled_14x15,const Icon, +Variable,+,I_Attention_5x8,const Icon, +Variable,+,I_Auth_62x31,const Icon, +Variable,+,I_BLE_Pairing_128x64,const Icon, +Variable,+,I_Background_128x11,const Icon, +Variable,+,I_BatteryBody_52x28,const Icon, +Variable,+,I_Battery_16x16,const Icon, +Variable,+,I_Battery_26x8,const Icon, +Variable,+,I_Ble_connected_15x15,const Icon, +Variable,+,I_Ble_disconnected_15x15,const Icon, +Variable,+,I_Bluetooth_Connected_16x8,const Icon, +Variable,+,I_Bluetooth_Idle_5x8,const Icon, +Variable,+,I_ButtonCenter_7x7,const Icon, +Variable,+,I_ButtonDown_7x4,const Icon, +Variable,+,I_ButtonLeftSmall_3x5,const Icon, +Variable,+,I_ButtonLeft_4x7,const Icon, +Variable,+,I_ButtonRightSmall_3x5,const Icon, +Variable,+,I_ButtonRight_4x7,const Icon, +Variable,+,I_ButtonUp_7x4,const Icon, +Variable,+,I_Button_18x18,const Icon, +Variable,+,I_Certification1_103x56,const Icon, +Variable,+,I_Certification2_98x33,const Icon, +Variable,+,I_Charging_lightning_9x10,const Icon, +Variable,+,I_Charging_lightning_mask_9x10,const Icon, +Variable,+,I_Circles_47x47,const Icon, +Variable,+,I_Clock_18x18,const Icon, +Variable,+,I_Connect_me_62x31,const Icon, +Variable,+,I_Connected_62x31,const Icon, +Variable,+,I_CoolHi_25x27,const Icon, +Variable,+,I_CoolHi_hvr_25x27,const Icon, +Variable,+,I_CoolLo_25x27,const Icon, +Variable,+,I_CoolLo_hvr_25x27,const Icon, +Variable,+,I_Cry_dolph_55x52,const Icon, +Variable,+,I_DFU_128x50,const Icon, +Variable,+,I_Dehumidify_25x27,const Icon, +Variable,+,I_Dehumidify_hvr_25x27,const Icon, +Variable,+,I_Detailed_chip_17x13,const Icon, +Variable,+,I_DolphinCommon_56x48,const Icon, +Variable,+,I_DolphinMafia_115x62,const Icon, +Variable,+,I_DolphinNice_96x59,const Icon, +Variable,+,I_DolphinReadingSuccess_59x63,const Icon, +Variable,+,I_DolphinWait_61x59,const Icon, +Variable,+,I_DoorLeft_70x55,const Icon, +Variable,+,I_DoorRight_70x55,const Icon, +Variable,+,I_Down_25x27,const Icon, +Variable,+,I_Down_hvr_25x27,const Icon, +Variable,+,I_Drive_112x35,const Icon, +Variable,+,I_Error_18x18,const Icon, +Variable,+,I_Error_62x31,const Icon, +Variable,+,I_EviSmile1_18x21,const Icon, +Variable,+,I_EviSmile2_18x21,const Icon, +Variable,+,I_EviWaiting1_18x21,const Icon, +Variable,+,I_EviWaiting2_18x21,const Icon, +Variable,+,I_FaceCharging_29x14,const Icon, +Variable,+,I_FaceConfused_29x14,const Icon, +Variable,+,I_FaceNopower_29x14,const Icon, +Variable,+,I_FaceNormal_29x14,const Icon, +Variable,+,I_GameMode_11x8,const Icon, +Variable,+,I_Health_16x16,const Icon, +Variable,+,I_HeatHi_25x27,const Icon, +Variable,+,I_HeatHi_hvr_25x27,const Icon, +Variable,+,I_HeatLo_25x27,const Icon, +Variable,+,I_HeatLo_hvr_25x27,const Icon, +Variable,+,I_InfraredArrowDown_4x8,const Icon, +Variable,+,I_InfraredArrowUp_4x8,const Icon, +Variable,+,I_InfraredLearnShort_128x31,const Icon, +Variable,+,I_KeyBackspaceSelected_16x9,const Icon, +Variable,+,I_KeyBackspace_16x9,const Icon, +Variable,+,I_KeySaveSelected_24x11,const Icon, +Variable,+,I_KeySave_24x11,const Icon, +Variable,+,I_Keychain_39x36,const Icon, +Variable,+,I_Left_mouse_icon_9x9,const Icon, +Variable,+,I_Lock_7x8,const Icon, +Variable,+,I_Lock_8x8,const Icon, +Variable,+,I_MHz_25x11,const Icon, +Variable,+,I_Medium_chip_22x21,const Icon, +Variable,+,I_Mute_25x27,const Icon, +Variable,+,I_Mute_hvr_25x27,const Icon, +Variable,+,I_NFC_manual_60x50,const Icon, +Variable,+,I_Nfc_10px,const Icon, +Variable,+,I_Off_25x27,const Icon, +Variable,+,I_Off_hvr_25x27,const Icon, +Variable,+,I_Ok_btn_9x9,const Icon, +Variable,+,I_Ok_btn_pressed_13x13,const Icon, +Variable,+,I_Percent_10x14,const Icon, +Variable,+,I_Pin_arrow_down_7x9,const Icon, +Variable,+,I_Pin_arrow_left_9x7,const Icon, +Variable,+,I_Pin_arrow_right_9x7,const Icon, +Variable,+,I_Pin_arrow_up_7x9,const Icon, +Variable,+,I_Pin_attention_dpad_29x29,const Icon, +Variable,+,I_Pin_back_arrow_10x8,const Icon, +Variable,+,I_Pin_back_full_40x8,const Icon, +Variable,+,I_Pin_pointer_5x3,const Icon, +Variable,+,I_Pin_star_7x7,const Icon, +Variable,+,I_Power_25x27,const Icon, +Variable,+,I_Power_hvr_25x27,const Icon, +Variable,+,I_Pressed_Button_13x13,const Icon, +Variable,+,I_Quest_7x8,const Icon, +Variable,+,I_RFIDBigChip_37x36,const Icon, +Variable,+,I_RFIDDolphinReceive_97x61,const Icon, +Variable,+,I_RFIDDolphinSend_97x61,const Icon, +Variable,+,I_RFIDDolphinSuccess_108x57,const Icon, +Variable,+,I_Reader_detect_43x40,const Icon, +Variable,+,I_Restoring_38x32,const Icon, +Variable,+,I_Right_mouse_icon_9x9,const Icon, +Variable,+,I_SDQuestion_35x43,const Icon, +Variable,+,I_SDcardFail_11x8,const Icon, +Variable,+,I_SDcardMounted_11x8,const Icon, +Variable,+,I_Scanning_123x52,const Icon, +Variable,+,I_Smile_18x18,const Icon, +Variable,+,I_Space_65x18,const Icon, +Variable,+,I_Tap_reader_36x38,const Icon, +Variable,+,I_Temperature_16x16,const Icon, +Variable,+,I_Unlock_7x8,const Icon, +Variable,+,I_Unplug_bg_bottom_128x10,const Icon, +Variable,+,I_Unplug_bg_top_128x14,const Icon, +Variable,+,I_Up_25x27,const Icon, +Variable,+,I_Up_hvr_25x27,const Icon, +Variable,+,I_Updating_32x40,const Icon, +Variable,+,I_UsbTree_48x22,const Icon, +Variable,+,I_Vol_down_25x27,const Icon, +Variable,+,I_Vol_down_hvr_25x27,const Icon, +Variable,+,I_Vol_up_25x27,const Icon, +Variable,+,I_Vol_up_hvr_25x27,const Icon, +Variable,+,I_Voldwn_6x6,const Icon, +Variable,+,I_Voltage_16x16,const Icon, +Variable,+,I_Volup_8x6,const Icon, +Variable,+,I_WarningDolphin_45x42,const Icon, +Variable,+,I_Warning_30x23,const Icon, +Variable,+,I_back_10px,const Icon, +Variable,+,I_badusb_10px,const Icon, +Variable,+,I_dir_10px,const Icon, +Variable,+,I_iButtonDolphinVerySuccess_108x52,const Icon, +Variable,+,I_iButtonKey_49x44,const Icon, +Variable,+,I_ibutt_10px,const Icon, +Variable,+,I_ir_10px,const Icon, +Variable,+,I_loading_10px,const Icon, +Variable,+,I_music_10px,const Icon, +Variable,+,I_passport_bad1_46x49,const Icon, +Variable,+,I_passport_bad2_46x49,const Icon, +Variable,+,I_passport_bad3_46x49,const Icon, +Variable,+,I_passport_bottom_128x18,const Icon, +Variable,+,I_passport_happy1_46x49,const Icon, +Variable,+,I_passport_happy2_46x49,const Icon, +Variable,+,I_passport_happy3_46x49,const Icon, +Variable,+,I_passport_left_6x46,const Icon, +Variable,+,I_passport_okay1_46x49,const Icon, +Variable,+,I_passport_okay2_46x49,const Icon, +Variable,+,I_passport_okay3_46x49,const Icon, +Variable,+,I_sub1_10px,const Icon, +Variable,+,I_u2f_10px,const Icon, +Variable,+,I_unknown_10px,const Icon, +Variable,+,I_update_10px,const Icon, +Variable,-,MSIRangeTable,const uint32_t[16], +Variable,-,SmpsPrescalerTable,const uint32_t[4][6], +Variable,+,SystemCoreClock,uint32_t, +Variable,+,_ctype_,const char[], +Variable,+,_global_impure_ptr,_reent*, +Variable,+,_impure_ptr,_reent*, +Variable,-,_sys_errlist,const char*[], +Variable,-,_sys_nerr,int, +Variable,+,cli_vcp,CliSession, +Variable,+,furi_hal_i2c_bus_external,FuriHalI2cBus, +Variable,+,furi_hal_i2c_bus_power,FuriHalI2cBus, +Variable,+,furi_hal_i2c_handle_external,FuriHalI2cBusHandle, +Variable,+,furi_hal_i2c_handle_power,FuriHalI2cBusHandle, +Variable,+,furi_hal_sd_spi_handle,FuriHalSpiBusHandle*, +Variable,+,furi_hal_spi_bus_d,FuriHalSpiBus, +Variable,+,furi_hal_spi_bus_handle_display,FuriHalSpiBusHandle, +Variable,+,furi_hal_spi_bus_handle_external,FuriHalSpiBusHandle, +Variable,+,furi_hal_spi_bus_handle_nfc,FuriHalSpiBusHandle, +Variable,+,furi_hal_spi_bus_handle_sd_fast,FuriHalSpiBusHandle, +Variable,+,furi_hal_spi_bus_handle_sd_slow,FuriHalSpiBusHandle, +Variable,+,furi_hal_spi_bus_handle_subghz,FuriHalSpiBusHandle, +Variable,+,furi_hal_spi_bus_r,FuriHalSpiBus, +Variable,+,furi_hal_spi_preset_1edge_low_16m,const LL_SPI_InitTypeDef, +Variable,+,furi_hal_spi_preset_1edge_low_2m,const LL_SPI_InitTypeDef, +Variable,+,furi_hal_spi_preset_1edge_low_4m,const LL_SPI_InitTypeDef, +Variable,+,furi_hal_spi_preset_1edge_low_8m,const LL_SPI_InitTypeDef, +Variable,+,furi_hal_spi_preset_2edge_low_8m,const LL_SPI_InitTypeDef, +Variable,+,gpio_button_back,const GpioPin, +Variable,+,gpio_button_down,const GpioPin, +Variable,+,gpio_button_left,const GpioPin, +Variable,+,gpio_button_ok,const GpioPin, +Variable,+,gpio_button_right,const GpioPin, +Variable,+,gpio_button_up,const GpioPin, +Variable,+,gpio_cc1101_g0,const GpioPin, +Variable,+,gpio_display_cs,const GpioPin, +Variable,+,gpio_display_di,const GpioPin, +Variable,+,gpio_display_rst_n,const GpioPin, +Variable,+,gpio_ext_pa4,const GpioPin, +Variable,+,gpio_ext_pa6,const GpioPin, +Variable,+,gpio_ext_pa7,const GpioPin, +Variable,+,gpio_ext_pb2,const GpioPin, +Variable,+,gpio_ext_pb3,const GpioPin, +Variable,+,gpio_ext_pc0,const GpioPin, +Variable,+,gpio_ext_pc1,const GpioPin, +Variable,+,gpio_ext_pc3,const GpioPin, +Variable,+,gpio_i2c_power_scl,const GpioPin, +Variable,+,gpio_i2c_power_sda,const GpioPin, +Variable,+,gpio_infrared_rx,const GpioPin, +Variable,+,gpio_infrared_tx,const GpioPin, +Variable,+,gpio_nfc_cs,const GpioPin, +Variable,+,gpio_nfc_irq_rfid_pull,const GpioPin, +Variable,+,gpio_rf_sw_0,const GpioPin, +Variable,+,gpio_rfid_carrier,const GpioPin, +Variable,+,gpio_rfid_carrier_out,const GpioPin, +Variable,+,gpio_rfid_data_in,const GpioPin, +Variable,+,gpio_sdcard_cd,const GpioPin, +Variable,+,gpio_sdcard_cs,const GpioPin, +Variable,+,gpio_speaker,const GpioPin, +Variable,+,gpio_spi_d_miso,const GpioPin, +Variable,+,gpio_spi_d_mosi,const GpioPin, +Variable,+,gpio_spi_d_sck,const GpioPin, +Variable,+,gpio_spi_r_miso,const GpioPin, +Variable,+,gpio_spi_r_mosi,const GpioPin, +Variable,+,gpio_spi_r_sck,const GpioPin, +Variable,+,gpio_subghz_cs,const GpioPin, +Variable,+,gpio_usart_rx,const GpioPin, +Variable,+,gpio_usart_tx,const GpioPin, +Variable,+,gpio_usb_dm,const GpioPin, +Variable,+,gpio_usb_dp,const GpioPin, +Variable,+,ibutton_gpio,const GpioPin, +Variable,+,input_pins,const InputPin[], +Variable,+,input_pins_count,const size_t, +Variable,+,lfrfid_protocols,const ProtocolBase*[], +Variable,+,message_blink_set_color_blue,const NotificationMessage, +Variable,+,message_blink_set_color_cyan,const NotificationMessage, +Variable,+,message_blink_set_color_green,const NotificationMessage, +Variable,+,message_blink_set_color_magenta,const NotificationMessage, +Variable,+,message_blink_set_color_red,const NotificationMessage, +Variable,+,message_blink_set_color_white,const NotificationMessage, +Variable,+,message_blink_set_color_yellow,const NotificationMessage, +Variable,+,message_blink_start_10,const NotificationMessage, +Variable,+,message_blink_start_100,const NotificationMessage, +Variable,+,message_blink_stop,const NotificationMessage, +Variable,+,message_blue_0,const NotificationMessage, +Variable,+,message_blue_255,const NotificationMessage, +Variable,+,message_click,const NotificationMessage, +Variable,+,message_delay_1,const NotificationMessage, +Variable,+,message_delay_10,const NotificationMessage, +Variable,+,message_delay_100,const NotificationMessage, +Variable,+,message_delay_1000,const NotificationMessage, +Variable,+,message_delay_25,const NotificationMessage, +Variable,+,message_delay_250,const NotificationMessage, +Variable,+,message_delay_50,const NotificationMessage, +Variable,+,message_delay_500,const NotificationMessage, +Variable,+,message_display_backlight_enforce_auto,const NotificationMessage, +Variable,+,message_display_backlight_enforce_on,const NotificationMessage, +Variable,+,message_display_backlight_off,const NotificationMessage, +Variable,+,message_display_backlight_on,const NotificationMessage, +Variable,+,message_do_not_reset,const NotificationMessage, +Variable,+,message_force_display_brightness_setting_1f,const NotificationMessage, +Variable,+,message_force_speaker_volume_setting_1f,const NotificationMessage, +Variable,+,message_force_vibro_setting_off,const NotificationMessage, +Variable,+,message_force_vibro_setting_on,const NotificationMessage, +Variable,+,message_green_0,const NotificationMessage, +Variable,+,message_green_255,const NotificationMessage, +Variable,+,message_note_a0,const NotificationMessage, +Variable,+,message_note_a1,const NotificationMessage, +Variable,+,message_note_a2,const NotificationMessage, +Variable,+,message_note_a3,const NotificationMessage, +Variable,+,message_note_a4,const NotificationMessage, +Variable,+,message_note_a5,const NotificationMessage, +Variable,+,message_note_a6,const NotificationMessage, +Variable,+,message_note_a7,const NotificationMessage, +Variable,+,message_note_a8,const NotificationMessage, +Variable,+,message_note_as0,const NotificationMessage, +Variable,+,message_note_as1,const NotificationMessage, +Variable,+,message_note_as2,const NotificationMessage, +Variable,+,message_note_as3,const NotificationMessage, +Variable,+,message_note_as4,const NotificationMessage, +Variable,+,message_note_as5,const NotificationMessage, +Variable,+,message_note_as6,const NotificationMessage, +Variable,+,message_note_as7,const NotificationMessage, +Variable,+,message_note_as8,const NotificationMessage, +Variable,+,message_note_b0,const NotificationMessage, +Variable,+,message_note_b1,const NotificationMessage, +Variable,+,message_note_b2,const NotificationMessage, +Variable,+,message_note_b3,const NotificationMessage, +Variable,+,message_note_b4,const NotificationMessage, +Variable,+,message_note_b5,const NotificationMessage, +Variable,+,message_note_b6,const NotificationMessage, +Variable,+,message_note_b7,const NotificationMessage, +Variable,+,message_note_b8,const NotificationMessage, +Variable,+,message_note_c0,const NotificationMessage, +Variable,+,message_note_c1,const NotificationMessage, +Variable,+,message_note_c2,const NotificationMessage, +Variable,+,message_note_c3,const NotificationMessage, +Variable,+,message_note_c4,const NotificationMessage, +Variable,+,message_note_c5,const NotificationMessage, +Variable,+,message_note_c6,const NotificationMessage, +Variable,+,message_note_c7,const NotificationMessage, +Variable,+,message_note_c8,const NotificationMessage, +Variable,+,message_note_cs0,const NotificationMessage, +Variable,+,message_note_cs1,const NotificationMessage, +Variable,+,message_note_cs2,const NotificationMessage, +Variable,+,message_note_cs3,const NotificationMessage, +Variable,+,message_note_cs4,const NotificationMessage, +Variable,+,message_note_cs5,const NotificationMessage, +Variable,+,message_note_cs6,const NotificationMessage, +Variable,+,message_note_cs7,const NotificationMessage, +Variable,+,message_note_cs8,const NotificationMessage, +Variable,+,message_note_d0,const NotificationMessage, +Variable,+,message_note_d1,const NotificationMessage, +Variable,+,message_note_d2,const NotificationMessage, +Variable,+,message_note_d3,const NotificationMessage, +Variable,+,message_note_d4,const NotificationMessage, +Variable,+,message_note_d5,const NotificationMessage, +Variable,+,message_note_d6,const NotificationMessage, +Variable,+,message_note_d7,const NotificationMessage, +Variable,+,message_note_d8,const NotificationMessage, +Variable,+,message_note_ds0,const NotificationMessage, +Variable,+,message_note_ds1,const NotificationMessage, +Variable,+,message_note_ds2,const NotificationMessage, +Variable,+,message_note_ds3,const NotificationMessage, +Variable,+,message_note_ds4,const NotificationMessage, +Variable,+,message_note_ds5,const NotificationMessage, +Variable,+,message_note_ds6,const NotificationMessage, +Variable,+,message_note_ds7,const NotificationMessage, +Variable,+,message_note_ds8,const NotificationMessage, +Variable,+,message_note_e0,const NotificationMessage, +Variable,+,message_note_e1,const NotificationMessage, +Variable,+,message_note_e2,const NotificationMessage, +Variable,+,message_note_e3,const NotificationMessage, +Variable,+,message_note_e4,const NotificationMessage, +Variable,+,message_note_e5,const NotificationMessage, +Variable,+,message_note_e6,const NotificationMessage, +Variable,+,message_note_e7,const NotificationMessage, +Variable,+,message_note_e8,const NotificationMessage, +Variable,+,message_note_f0,const NotificationMessage, +Variable,+,message_note_f1,const NotificationMessage, +Variable,+,message_note_f2,const NotificationMessage, +Variable,+,message_note_f3,const NotificationMessage, +Variable,+,message_note_f4,const NotificationMessage, +Variable,+,message_note_f5,const NotificationMessage, +Variable,+,message_note_f6,const NotificationMessage, +Variable,+,message_note_f7,const NotificationMessage, +Variable,+,message_note_f8,const NotificationMessage, +Variable,+,message_note_fs0,const NotificationMessage, +Variable,+,message_note_fs1,const NotificationMessage, +Variable,+,message_note_fs2,const NotificationMessage, +Variable,+,message_note_fs3,const NotificationMessage, +Variable,+,message_note_fs4,const NotificationMessage, +Variable,+,message_note_fs5,const NotificationMessage, +Variable,+,message_note_fs6,const NotificationMessage, +Variable,+,message_note_fs7,const NotificationMessage, +Variable,+,message_note_fs8,const NotificationMessage, +Variable,+,message_note_g0,const NotificationMessage, +Variable,+,message_note_g1,const NotificationMessage, +Variable,+,message_note_g2,const NotificationMessage, +Variable,+,message_note_g3,const NotificationMessage, +Variable,+,message_note_g4,const NotificationMessage, +Variable,+,message_note_g5,const NotificationMessage, +Variable,+,message_note_g6,const NotificationMessage, +Variable,+,message_note_g7,const NotificationMessage, +Variable,+,message_note_g8,const NotificationMessage, +Variable,+,message_note_gs0,const NotificationMessage, +Variable,+,message_note_gs1,const NotificationMessage, +Variable,+,message_note_gs2,const NotificationMessage, +Variable,+,message_note_gs3,const NotificationMessage, +Variable,+,message_note_gs4,const NotificationMessage, +Variable,+,message_note_gs5,const NotificationMessage, +Variable,+,message_note_gs6,const NotificationMessage, +Variable,+,message_note_gs7,const NotificationMessage, +Variable,+,message_note_gs8,const NotificationMessage, +Variable,+,message_red_0,const NotificationMessage, +Variable,+,message_red_255,const NotificationMessage, +Variable,+,message_sound_off,const NotificationMessage, +Variable,+,message_vibro_off,const NotificationMessage, +Variable,+,message_vibro_on,const NotificationMessage, +Variable,+,periph_power,const GpioPin, +Variable,+,sequence_audiovisual_alert,const NotificationSequence, +Variable,+,sequence_blink_blue_10,const NotificationSequence, +Variable,+,sequence_blink_blue_100,const NotificationSequence, +Variable,+,sequence_blink_cyan_10,const NotificationSequence, +Variable,+,sequence_blink_cyan_100,const NotificationSequence, +Variable,+,sequence_blink_green_10,const NotificationSequence, +Variable,+,sequence_blink_green_100,const NotificationSequence, +Variable,+,sequence_blink_magenta_10,const NotificationSequence, +Variable,+,sequence_blink_magenta_100,const NotificationSequence, +Variable,+,sequence_blink_red_10,const NotificationSequence, +Variable,+,sequence_blink_red_100,const NotificationSequence, +Variable,+,sequence_blink_start_blue,const NotificationSequence, +Variable,+,sequence_blink_start_cyan,const NotificationSequence, +Variable,+,sequence_blink_start_green,const NotificationSequence, +Variable,+,sequence_blink_start_magenta,const NotificationSequence, +Variable,+,sequence_blink_start_red,const NotificationSequence, +Variable,+,sequence_blink_start_yellow,const NotificationSequence, +Variable,+,sequence_blink_stop,const NotificationSequence, +Variable,+,sequence_blink_white_100,const NotificationSequence, +Variable,+,sequence_blink_yellow_10,const NotificationSequence, +Variable,+,sequence_blink_yellow_100,const NotificationSequence, +Variable,+,sequence_charged,const NotificationSequence, +Variable,+,sequence_charging,const NotificationSequence, +Variable,+,sequence_display_backlight_enforce_auto,const NotificationSequence, +Variable,+,sequence_display_backlight_enforce_on,const NotificationSequence, +Variable,+,sequence_display_backlight_off,const NotificationSequence, +Variable,+,sequence_display_backlight_off_delay_1000,const NotificationSequence, +Variable,+,sequence_display_backlight_on,const NotificationSequence, +Variable,+,sequence_double_vibro,const NotificationSequence, +Variable,+,sequence_error,const NotificationSequence, +Variable,+,sequence_not_charging,const NotificationSequence, +Variable,+,sequence_reset_blue,const NotificationSequence, +Variable,+,sequence_reset_display,const NotificationSequence, +Variable,+,sequence_reset_green,const NotificationSequence, +Variable,+,sequence_reset_red,const NotificationSequence, +Variable,+,sequence_reset_rgb,const NotificationSequence, +Variable,+,sequence_reset_sound,const NotificationSequence, +Variable,+,sequence_reset_vibro,const NotificationSequence, +Variable,+,sequence_set_blue_255,const NotificationSequence, +Variable,+,sequence_set_green_255,const NotificationSequence, +Variable,+,sequence_set_only_blue_255,const NotificationSequence, +Variable,+,sequence_set_only_green_255,const NotificationSequence, +Variable,+,sequence_set_only_red_255,const NotificationSequence, +Variable,+,sequence_set_red_255,const NotificationSequence, +Variable,+,sequence_set_vibro_on,const NotificationSequence, +Variable,+,sequence_single_vibro,const NotificationSequence, +Variable,+,sequence_solid_yellow,const NotificationSequence, +Variable,+,sequence_success,const NotificationSequence, +Variable,+,subghz_protocol_raw,const SubGhzProtocol, +Variable,+,subghz_protocol_raw_decoder,const SubGhzProtocolDecoder, +Variable,+,subghz_protocol_raw_encoder,const SubGhzProtocolEncoder, +Variable,-,suboptarg,char*, +Variable,+,usb_cdc_dual,FuriHalUsbInterface, +Variable,+,usb_cdc_single,FuriHalUsbInterface, +Variable,+,usb_hid,FuriHalUsbInterface, +Variable,+,usb_hid_u2f,FuriHalUsbInterface, +Variable,+,usbd_devfs,const usbd_driver, +Variable,+,vibro_gpio,const GpioPin, diff --git a/firmware/targets/f7/application-ext.ld b/firmware/targets/f7/application-ext.ld index 45fe431c..8f79675b 100644 --- a/firmware/targets/f7/application-ext.ld +++ b/firmware/targets/f7/application-ext.ld @@ -1,9 +1,17 @@ +FORCE_COMMON_ALLOCATION + SECTIONS { - .text 0x00000000 : + .text 0x00000000 : ALIGN(4) { *(.text) + *(.stub) + *(.text*) *(.text.*) + *(.text._*) + + KEEP (*(.init)) + KEEP (*(.fini)) } .rodata : @@ -20,15 +28,22 @@ SECTIONS *(.data.*) } + .bss : { *(.bss) - *(.bss.*) + *(.bss*) *(.sbss) - *(.sbss.*) + *(.sbss*) *(COMMON) } + .ARM.attributes : + { + *(.ARM.attributes) + *(.ARM.attributes.*) + } + /DISCARD/ : { *(.comment) diff --git a/firmware/targets/f7/furi_hal/furi_hal_clock.h b/firmware/targets/f7/furi_hal/furi_hal_clock.h index 9cb11db4..6cebb20c 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_clock.h +++ b/firmware/targets/f7/furi_hal/furi_hal_clock.h @@ -1,5 +1,9 @@ #pragma once +#ifdef __cplusplus +extern "C" { +#endif + /** Early initialization */ void furi_hal_clock_init_early(); @@ -20,3 +24,7 @@ void furi_hal_clock_suspend_tick(); /** Continue SysTick counter operation */ void furi_hal_clock_resume_tick(); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/f7/furi_hal/furi_hal_flash.h b/firmware/targets/f7/furi_hal/furi_hal_flash.h index eac80d95..1ed4c039 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_flash.h +++ b/firmware/targets/f7/furi_hal/furi_hal_flash.h @@ -4,6 +4,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define FURI_HAL_FLASH_OB_RAW_SIZE_BYTES 0x80 #define FURI_HAL_FLASH_OB_SIZE_WORDS (FURI_HAL_FLASH_OB_RAW_SIZE_BYTES / sizeof(uint32_t)) #define FURI_HAL_FLASH_OB_TOTAL_VALUES (FURI_HAL_FLASH_OB_SIZE_WORDS / 2) @@ -142,3 +146,7 @@ void furi_hal_flash_ob_apply(); * @return pointer to read-only data of OB (raw + complementary values) */ const FuriHalFlashRawOptionByteData* furi_hal_flash_ob_get_raw_ptr(); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index 94677481..de67bbc3 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -39,6 +39,10 @@ bool furi_hal_nfc_is_busy() { return rfalNfcGetState() != RFAL_NFC_STATE_IDLE; } +bool furi_hal_nfc_is_init() { + return rfalNfcGetState() != RFAL_NFC_STATE_NOTINIT; +} + void furi_hal_nfc_field_on() { furi_hal_nfc_exit_sleep(); st25r3916TxRxOn(); @@ -124,9 +128,9 @@ bool furi_hal_nfc_detect(FuriHalNfcDevData* nfc_data, uint32_t timeout) { } nfc_data->cuid = (cuid_start[0] << 24) | (cuid_start[1] << 16) | (cuid_start[2] << 8) | (cuid_start[3]); - } else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCB || - dev_list[0].type == RFAL_NFC_LISTEN_TYPE_ST25TB) - { + } else if( + dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCB || + dev_list[0].type == RFAL_NFC_LISTEN_TYPE_ST25TB) { nfc_data->type = FuriHalNfcTypeB; } else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCF) { nfc_data->type = FuriHalNfcTypeF; @@ -738,3 +742,46 @@ void furi_hal_nfc_sleep() { rfalNfcDeactivate(false); rfalLowPowerModeStart(); } + +FuriHalNfcReturn furi_hal_nfc_ll_set_mode(FuriHalNfcMode mode, FuriHalNfcBitrate txBR, FuriHalNfcBitrate rxBR) { + return rfalSetMode((rfalMode)mode, (rfalBitRate)txBR, (rfalBitRate)rxBR); +} + +void furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandling eHandling) { + rfalSetErrorHandling((rfalEHandling)eHandling); +} + +void furi_hal_nfc_ll_set_guard_time(uint32_t cycles) { + rfalSetGT(cycles); +} + +void furi_hal_nfc_ll_set_fdt_listen(uint32_t cycles) { + rfalSetFDTListen(cycles); +} + +void furi_hal_nfc_ll_set_fdt_poll(uint32_t FDTPoll) { + rfalSetFDTPoll(FDTPoll); +} + +void furi_hal_nfc_ll_txrx_on() { + st25r3916TxRxOn(); +} + +void furi_hal_nfc_ll_txrx_off() { + st25r3916TxRxOff(); +} + +FuriHalNfcReturn furi_hal_nfc_ll_txrx( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt) { + return rfalTransceiveBlockingTxRx(txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt); +} + +void furi_hal_nfc_ll_poll() { + rfalWorker(); +} \ No newline at end of file diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index 7afb88bc..b73d074f 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -17,7 +17,6 @@ #define TAG "FuriHalSubGhz" - /* * Uncomment define to enable duplication of * IO GO0 CC1101 to an external comb. @@ -33,7 +32,7 @@ * Attention this setting switches pin to output. * Make sure it is not connected directly to power or ground */ - + //#define SUBGHZ_DEBUG_CC1101_PIN gpio_ext_pa7 #ifdef SUBGHZ_DEBUG_CC1101_PIN uint32_t subghz_debug_gpio_buff[2]; diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c b/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c index 69a7fb3c..88deafdc 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c @@ -1,7 +1,7 @@ #include "furi_hal_version.h" #include "furi_hal_usb_i.h" #include "furi_hal_usb.h" -#include "furi_hal_usb_cdc_i.h" +#include "furi_hal_usb_cdc.h" #include #include "usb.h" diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_cdc_i.h b/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.h similarity index 91% rename from firmware/targets/f7/furi_hal/furi_hal_usb_cdc_i.h rename to firmware/targets/f7/furi_hal/furi_hal_usb_cdc.h index 4ba150eb..89b68991 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb_cdc_i.h +++ b/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.h @@ -5,6 +5,10 @@ #define CDC_DATA_SZ 64 +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { void (*tx_ep_callback)(void* context); void (*rx_ep_callback)(void* context); @@ -22,3 +26,7 @@ uint8_t furi_hal_cdc_get_ctrl_line_state(uint8_t if_num); void furi_hal_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len); int32_t furi_hal_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/f7/platform_specific/intrinsic_export.h b/firmware/targets/f7/platform_specific/intrinsic_export.h new file mode 100644 index 00000000..8dbc4bd0 --- /dev/null +++ b/firmware/targets/f7/platform_specific/intrinsic_export.h @@ -0,0 +1,11 @@ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void __clear_cache(void*, void*); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/f7/stm32wb55xx_flash.ld b/firmware/targets/f7/stm32wb55xx_flash.ld index 4124c096..e1fb98b9 100644 --- a/firmware/targets/f7/stm32wb55xx_flash.ld +++ b/firmware/targets/f7/stm32wb55xx_flash.ld @@ -131,7 +131,7 @@ SECTIONS _sidata = LOADADDR(.data); /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : + .data : { . = ALIGN(4); _sdata = .; /* create a global symbol at data start */ @@ -143,7 +143,6 @@ SECTIONS _edata = .; /* define a global symbol at data end */ } >RAM1 AT> FLASH - /* Uninitialized data section */ . = ALIGN(4); .bss : @@ -161,7 +160,8 @@ SECTIONS } >RAM1 /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack(NOLOAD): + /* DSECT: https://software-dl.ti.com/ccs/esd/documents/sdto_cgt_linker_special_section_types.html */ + ._user_heap_stack(DSECT): { . = ALIGN(8); __heap_start__ = .; @@ -172,11 +172,11 @@ SECTIONS } >RAM1 /* Free Flash space, that can be used for internal storage */ - .free_flash(NOLOAD): + .free_flash(DSECT): { __free_flash_start__ = .; . = ORIGIN(FLASH) + LENGTH(FLASH); - } >FLASH + } >FLASH /* Remove information from the standard libraries */ /DISCARD/ : diff --git a/firmware/targets/f7/stm32wb55xx_ram_fw.ld b/firmware/targets/f7/stm32wb55xx_ram_fw.ld index 1b7fe360..db9e407c 100644 --- a/firmware/targets/f7/stm32wb55xx_ram_fw.ld +++ b/firmware/targets/f7/stm32wb55xx_ram_fw.ld @@ -159,7 +159,7 @@ SECTIONS } >RAM1 /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : + ._user_heap_stack(DSECT) : { . = ALIGN(8); __heap_start__ = .; @@ -170,7 +170,7 @@ SECTIONS } >RAM1 /* Free Flash space, that can be used for internal storage */ - /*.free_flash(NOLOAD): + /*.free_flash(DSECT): { __free_flash_start__ = .; . = ORIGIN(FLASH) + LENGTH(FLASH); diff --git a/firmware/targets/furi_hal_include/furi_hal.h b/firmware/targets/furi_hal_include/furi_hal.h index 2a372a6c..8613c4d5 100644 --- a/firmware/targets/furi_hal_include/furi_hal.h +++ b/firmware/targets/furi_hal_include/furi_hal.h @@ -6,7 +6,8 @@ #pragma once #ifdef __cplusplus -template struct STOP_EXTERNING_ME {}; +template +struct STOP_EXTERNING_ME {}; #endif #include "furi_hal_cortex.h" diff --git a/firmware/targets/furi_hal_include/furi_hal_bt_hid.h b/firmware/targets/furi_hal_include/furi_hal_bt_hid.h index e35edd01..4e74bbda 100644 --- a/firmware/targets/furi_hal_include/furi_hal_bt_hid.h +++ b/firmware/targets/furi_hal_include/furi_hal_bt_hid.h @@ -3,6 +3,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** Start Hid Keyboard Profile */ void furi_hal_bt_hid_start(); @@ -81,3 +85,7 @@ bool furi_hal_bt_hid_consumer_key_release(uint16_t button); * @param button key code */ bool furi_hal_bt_hid_consumer_key_release_all(); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/furi_hal_include/furi_hal_bt_serial.h b/firmware/targets/furi_hal_include/furi_hal_bt_serial.h index 9cc4ba5b..e1b7af22 100644 --- a/firmware/targets/furi_hal_include/furi_hal_bt_serial.h +++ b/firmware/targets/furi_hal_include/furi_hal_bt_serial.h @@ -2,6 +2,10 @@ #include "serial_service.h" +#ifdef __cplusplus +extern "C" { +#endif + #define FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX SERIAL_SVC_DATA_LEN_MAX /** Serial service callback type */ @@ -38,3 +42,7 @@ void furi_hal_bt_serial_notify_buffer_is_empty(); * @return true on success */ bool furi_hal_bt_serial_tx(uint8_t* data, uint16_t size); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/furi_hal_include/furi_hal_compress.h b/firmware/targets/furi_hal_include/furi_hal_compress.h index 17ce3e69..f80aee51 100644 --- a/firmware/targets/furi_hal_include/furi_hal_compress.h +++ b/firmware/targets/furi_hal_include/furi_hal_compress.h @@ -8,6 +8,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** Defines encoder and decoder window size */ #define FURI_HAL_COMPRESS_EXP_BUFF_SIZE_LOG (8) @@ -77,3 +81,7 @@ bool furi_hal_compress_decode( uint8_t* data_out, size_t data_out_size, size_t* data_res_size); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/furi_hal_include/furi_hal_crypto.h b/firmware/targets/furi_hal_include/furi_hal_crypto.h index fc3974bb..81788e96 100644 --- a/firmware/targets/furi_hal_include/furi_hal_crypto.h +++ b/firmware/targets/furi_hal_include/furi_hal_crypto.h @@ -8,6 +8,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** FuriHalCryptoKey Type */ typedef enum { FuriHalCryptoKeyTypeMaster, /**< Master key */ @@ -82,3 +86,7 @@ bool furi_hal_crypto_encrypt(const uint8_t* input, uint8_t* output, size_t size) * @return true on success */ bool furi_hal_crypto_decrypt(const uint8_t* input, uint8_t* output, size_t size); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/furi_hal_include/furi_hal_nfc.h b/firmware/targets/furi_hal_include/furi_hal_nfc.h index 0bcb4506..537e0abf 100644 --- a/firmware/targets/furi_hal_include/furi_hal_nfc.h +++ b/firmware/targets/furi_hal_include/furi_hal_nfc.h @@ -5,16 +5,15 @@ #pragma once -#include #include #include #include -#include - #ifdef __cplusplus extern "C" { #endif +#include +#include #define FURI_HAL_NFC_UID_MAX_LEN 10 #define FURI_HAL_NFC_DATA_BUFF_SIZE (512) @@ -108,6 +107,12 @@ void furi_hal_nfc_init(); */ bool furi_hal_nfc_is_busy(); +/** Check if nfc is initialized + * + * @return true if initialized + */ + bool furi_hal_nfc_is_init(); + /** NFC field on */ void furi_hal_nfc_field_on(); @@ -229,6 +234,158 @@ void furi_hal_nfc_sleep(); void furi_hal_nfc_stop(); + +/* Low level transport API, use it to implement your own transport layers */ + +#define furi_hal_nfc_ll_ms2fc rfalConvMsTo1fc + +#define FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL RFAL_TXRX_FLAGS_CRC_TX_MANUAL +#define FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON RFAL_TXRX_FLAGS_AGC_ON +#define FURI_HAL_NFC_LL_TXRX_FLAGS_PAR_RX_REMV RFAL_TXRX_FLAGS_PAR_RX_REMV +#define FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP RFAL_TXRX_FLAGS_CRC_RX_KEEP + +typedef enum { + FuriHalNfcReturnOk = 0, /*!< no error occurred */ + FuriHalNfcReturnNomem = 1, /*!< not enough memory to perform the requested operation */ + FuriHalNfcReturnBusy = 2, /*!< device or resource busy */ + FuriHalNfcReturnIo = 3, /*!< generic IO error */ + FuriHalNfcReturnTimeout = 4, /*!< error due to timeout */ + FuriHalNfcReturnRequest = 5, /*!< invalid request or requested function can't be executed at the moment */ + FuriHalNfcReturnNomsg = 6, /*!< No message of desired type */ + FuriHalNfcReturnParam = 7, /*!< Parameter error */ + FuriHalNfcReturnSystem = 8, /*!< System error */ + FuriHalNfcReturnFraming = 9, /*!< Framing error */ + FuriHalNfcReturnOverrun = 10, /*!< lost one or more received bytes */ + FuriHalNfcReturnProto = 11, /*!< protocol error */ + FuriHalNfcReturnInternal = 12, /*!< Internal Error */ + FuriHalNfcReturnAgain = 13, /*!< Call again */ + FuriHalNfcReturnMemCorrupt = 14, /*!< memory corruption */ + FuriHalNfcReturnNotImplemented = 15, /*!< not implemented */ + FuriHalNfcReturnPcCorrupt = 16, /*!< Program Counter has been manipulated or spike/noise trigger illegal operation */ + FuriHalNfcReturnSend = 17, /*!< error sending*/ + FuriHalNfcReturnIgnore = 18, /*!< indicates error detected but to be ignored */ + FuriHalNfcReturnSemantic = 19, /*!< indicates error in state machine (unexpected cmd) */ + FuriHalNfcReturnSyntax = 20, /*!< indicates error in state machine (unknown cmd) */ + FuriHalNfcReturnCrc = 21, /*!< crc error */ + FuriHalNfcReturnNotfound = 22, /*!< transponder not found */ + FuriHalNfcReturnNotunique = 23, /*!< transponder not unique - more than one transponder in field */ + FuriHalNfcReturnNotsupp = 24, /*!< requested operation not supported */ + FuriHalNfcReturnWrite = 25, /*!< write error */ + FuriHalNfcReturnFifo = 26, /*!< fifo over or underflow error */ + FuriHalNfcReturnPar = 27, /*!< parity error */ + FuriHalNfcReturnDone = 28, /*!< transfer has already finished */ + FuriHalNfcReturnRfCollision = 29, /*!< collision error (Bit Collision or during RF Collision avoidance ) */ + FuriHalNfcReturnHwOverrun = 30, /*!< lost one or more received bytes */ + FuriHalNfcReturnReleaseReq = 31, /*!< device requested release */ + FuriHalNfcReturnSleepReq = 32, /*!< device requested sleep */ + FuriHalNfcReturnWrongState = 33, /*!< incorrent state for requested operation */ + FuriHalNfcReturnMaxReruns = 34, /*!< blocking procedure reached maximum runs */ + FuriHalNfcReturnDisabled = 35, /*!< operation aborted due to disabled configuration */ + FuriHalNfcReturnHwMismatch = 36, /*!< expected hw do not match */ + FuriHalNfcReturnLinkLoss = 37, /*!< Other device's field didn't behave as expected: turned off by Initiator in Passive mode, or AP2P did not turn on field */ + FuriHalNfcReturnInvalidHandle = 38, /*!< invalid or not initalized device handle */ + FuriHalNfcReturnIncompleteByte = 40, /*!< Incomplete byte rcvd */ + FuriHalNfcReturnIncompleteByte01 = 41, /*!< Incomplete byte rcvd - 1 bit */ + FuriHalNfcReturnIncompleteByte02 = 42, /*!< Incomplete byte rcvd - 2 bit */ + FuriHalNfcReturnIncompleteByte03 = 43, /*!< Incomplete byte rcvd - 3 bit */ + FuriHalNfcReturnIncompleteByte04 = 44, /*!< Incomplete byte rcvd - 4 bit */ + FuriHalNfcReturnIncompleteByte05 = 45, /*!< Incomplete byte rcvd - 5 bit */ + FuriHalNfcReturnIncompleteByte06 = 46, /*!< Incomplete byte rcvd - 6 bit */ + FuriHalNfcReturnIncompleteByte07 = 47, /*!< Incomplete byte rcvd - 7 bit */ +} FuriHalNfcReturn; + +typedef enum { + FuriHalNfcModeNone = 0, /*!< No mode selected/defined */ + FuriHalNfcModePollNfca = 1, /*!< Mode to perform as NFCA (ISO14443A) Poller (PCD) */ + FuriHalNfcModePollNfcaT1t = 2, /*!< Mode to perform as NFCA T1T (Topaz) Poller (PCD) */ + FuriHalNfcModePollNfcb = 3, /*!< Mode to perform as NFCB (ISO14443B) Poller (PCD) */ + FuriHalNfcModePollBPrime = 4, /*!< Mode to perform as B' Calypso (Innovatron) (PCD) */ + FuriHalNfcModePollBCts = 5, /*!< Mode to perform as CTS Poller (PCD) */ + FuriHalNfcModePollNfcf = 6, /*!< Mode to perform as NFCF (FeliCa) Poller (PCD) */ + FuriHalNfcModePollNfcv = 7, /*!< Mode to perform as NFCV (ISO15963) Poller (PCD) */ + FuriHalNfcModePollPicopass = 8, /*!< Mode to perform as PicoPass / iClass Poller (PCD) */ + FuriHalNfcModePollActiveP2p = 9, /*!< Mode to perform as Active P2P (ISO18092) Initiator */ + FuriHalNfcModeListenNfca = 10, /*!< Mode to perform as NFCA (ISO14443A) Listener (PICC) */ + FuriHalNfcModeListenNfcb = 11, /*!< Mode to perform as NFCA (ISO14443B) Listener (PICC) */ + FuriHalNfcModeListenNfcf = 12, /*!< Mode to perform as NFCA (ISO15963) Listener (PICC) */ + FuriHalNfcModeListenActiveP2p = 13 /*!< Mode to perform as Active P2P (ISO18092) Target */ +} FuriHalNfcMode; + +typedef enum { + FuriHalNfcBitrate106 = 0, /*!< Bit Rate 106 kbit/s (fc/128) */ + FuriHalNfcBitrate212 = 1, /*!< Bit Rate 212 kbit/s (fc/64) */ + FuriHalNfcBitrate424 = 2, /*!< Bit Rate 424 kbit/s (fc/32) */ + FuriHalNfcBitrate848 = 3, /*!< Bit Rate 848 kbit/s (fc/16) */ + FuriHalNfcBitrate1695 = 4, /*!< Bit Rate 1695 kbit/s (fc/8) */ + FuriHalNfcBitrate3390 = 5, /*!< Bit Rate 3390 kbit/s (fc/4) */ + FuriHalNfcBitrate6780 = 6, /*!< Bit Rate 6780 kbit/s (fc/2) */ + FuriHalNfcBitrate13560 = 7, /*!< Bit Rate 13560 kbit/s (fc) */ + FuriHalNfcBitrate52p97 = 0xEB, /*!< Bit Rate 52.97 kbit/s (fc/256) Fast Mode VICC->VCD */ + FuriHalNfcBitrate26p48 = 0xEC, /*!< Bit Rate 26,48 kbit/s (fc/512) NFCV VICC->VCD & VCD->VICC 1of4 */ + FuriHalNfcBitrate1p66 = 0xED, /*!< Bit Rate 1,66 kbit/s (fc/8192) NFCV VCD->VICC 1of256 */ + FuriHalNfcBitrateKeep = 0xFF /*!< Value indicating to keep the same previous bit rate */ +} FuriHalNfcBitrate; + +FuriHalNfcReturn furi_hal_nfc_ll_set_mode(FuriHalNfcMode mode, FuriHalNfcBitrate txBR, FuriHalNfcBitrate rxBR); + +#define FURI_HAL_NFC_LL_GT_NFCA furi_hal_nfc_ll_ms2fc(5U) /*!< GTA Digital 2.0 6.10.4.1 & B.2 */ +#define FURI_HAL_NFC_LL_GT_NFCB furi_hal_nfc_ll_ms2fc(5U) /*!< GTB Digital 2.0 7.9.4.1 & B.3 */ +#define FURI_HAL_NFC_LL_GT_NFCF furi_hal_nfc_ll_ms2fc(20U) /*!< GTF Digital 2.0 8.7.4.1 & B.4 */ +#define FURI_HAL_NFC_LL_GT_NFCV furi_hal_nfc_ll_ms2fc(5U) /*!< GTV Digital 2.0 9.7.5.1 & B.5 */ +#define FURI_HAL_NFC_LL_GT_PICOPASS furi_hal_nfc_ll_ms2fc(1U) /*!< GT Picopass */ +#define FURI_HAL_NFC_LL_GT_AP2P furi_hal_nfc_ll_ms2fc(5U) /*!< TIRFG Ecma 340 11.1.1 */ +#define FURI_HAL_NFC_LL_GT_AP2P_ADJUSTED furi_hal_nfc_ll_ms2fc(5U + 25U) /*!< Adjusted GT for greater interoperability (Sony XPERIA P, Nokia N9, Huawei P2) */ + +void furi_hal_nfc_ll_set_guard_time(uint32_t cycles); + +typedef enum { + FuriHalNfcErrorHandlingNone = 0, /*!< No special error handling will be performed */ + FuriHalNfcErrorHandlingNfc = 1, /*!< Error handling set to perform as NFC compliant device */ + FuriHalNfcErrorHandlingEmvco = 2 /*!< Error handling set to perform as EMVCo compliant device */ +} FuriHalNfcErrorHandling; + +void furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandling eHandling); + +/* RFAL Frame Delay Time (FDT) Listen default values */ +#define FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER 1172U /*!< FDTA,LISTEN,MIN (n=9) Last bit: Logic "1" - tnn,min/2 Digital 1.1 6.10 ; EMV CCP Spec Book D v2.01 4.8.1.3 */ +#define FURI_HAL_NFC_LL_FDT_LISTEN_NFCB_POLLER 1008U /*!< TR0B,MIN Digital 1.1 7.1.3 & A.3 ; EMV CCP Spec Book D v2.01 4.8.1.3 & Table A.5 */ +#define FURI_HAL_NFC_LL_FDT_LISTEN_NFCF_POLLER 2672U /*!< TR0F,LISTEN,MIN Digital 1.1 8.7.1.1 & A.4 */ +#define FURI_HAL_NFC_LL_FDT_LISTEN_NFCV_POLLER 4310U /*!< FDTV,LISTEN,MIN t1 min Digital 2.1 B.5 ; ISO15693-3 2009 9.1 */ +#define FURI_HAL_NFC_LL_FDT_LISTEN_PICOPASS_POLLER 3400U /*!< ISO15693 t1 min - observed adjustment */ +#define FURI_HAL_NFC_LL_FDT_LISTEN_AP2P_POLLER 64U /*!< FDT AP2P No actual FDTListen is required as fields switch and collision avoidance */ +#define FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_LISTENER 1172U /*!< FDTA,LISTEN,MIN Digital 1.1 6.10 */ +#define FURI_HAL_NFC_LL_FDT_LISTEN_NFCB_LISTENER 1024U /*!< TR0B,MIN Digital 1.1 7.1.3 & A.3 ; EMV CCP Spec Book D v2.01 4.8.1.3 & Table A.5 */ +#define FURI_HAL_NFC_LL_FDT_LISTEN_NFCF_LISTENER 2688U /*!< TR0F,LISTEN,MIN Digital 2.1 8.7.1.1 & B.4 */ +#define FURI_HAL_NFC_LL_FDT_LISTEN_AP2P_LISTENER 64U /*!< FDT AP2P No actual FDTListen exists as fields switch and collision avoidance */ + +void furi_hal_nfc_ll_set_fdt_listen(uint32_t cycles); + +/* RFAL Frame Delay Time (FDT) Poll default values */ +#define FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER 6780U /*!< FDTA,POLL,MIN Digital 1.1 6.10.3.1 & A.2 */ +#define FURI_HAL_NFC_LL_FDT_POLL_NFCA_T1T_POLLER 384U /*!< RRDDT1T,MIN,B1 Digital 1.1 10.7.1 & A.5 */ +#define FURI_HAL_NFC_LL_FDT_POLL_NFCB_POLLER 6780U /*!< FDTB,POLL,MIN = TR2B,MIN,DEFAULT Digital 1.1 7.9.3 & A.3 ; EMVCo 3.0 FDTB,PCD,MIN Table A.5 */ +#define FURI_HAL_NFC_LL_FDT_POLL_NFCF_POLLER 6800U /*!< FDTF,POLL,MIN Digital 2.1 8.7.3 & B.4 */ +#define FURI_HAL_NFC_LL_FDT_POLL_NFCV_POLLER 4192U /*!< FDTV,POLL Digital 2.1 9.7.3.1 & B.5 */ +#define FURI_HAL_NFC_LL_FDT_POLL_PICOPASS_POLLER 1790U /*!< FDT Max */ +#define FURI_HAL_NFC_LL_FDT_POLL_AP2P_POLLER 0U /*!< FDT AP2P No actual FDTPoll exists as fields switch and collision avoidance */ + +void furi_hal_nfc_ll_set_fdt_poll(uint32_t FDTPoll); + +void furi_hal_nfc_ll_txrx_on(); + +void furi_hal_nfc_ll_txrx_off(); + +FuriHalNfcReturn furi_hal_nfc_ll_txrx( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt); + +void furi_hal_nfc_ll_poll(); + #ifdef __cplusplus } #endif diff --git a/firmware/targets/furi_hal_include/furi_hal_power.h b/firmware/targets/furi_hal_include/furi_hal_power.h index 16af959c..3ab30c42 100644 --- a/firmware/targets/furi_hal_include/furi_hal_power.h +++ b/firmware/targets/furi_hal_include/furi_hal_power.h @@ -156,12 +156,6 @@ float furi_hal_power_get_battery_current(FuriHalPowerIC ic); */ float furi_hal_power_get_battery_temperature(FuriHalPowerIC ic); -/** Get System voltage in V - * - * @return voltage in V - */ -float furi_hal_power_get_system_voltage(); - /** Get USB voltage in V * * @return voltage in V diff --git a/firmware/targets/furi_hal_include/furi_hal_region.h b/firmware/targets/furi_hal_include/furi_hal_region.h index 10d519ab..accd7e12 100644 --- a/firmware/targets/furi_hal_include/furi_hal_region.h +++ b/firmware/targets/furi_hal_include/furi_hal_region.h @@ -4,6 +4,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { uint32_t start; uint32_t end; @@ -71,3 +75,7 @@ bool furi_hal_region_is_frequency_allowed(uint32_t frequency); * @return { description_of_the_return_value } */ const FuriHalRegionBand* furi_hal_region_get_band(uint32_t frequency); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/furi_hal_include/furi_hal_usb.h b/firmware/targets/furi_hal_include/furi_hal_usb.h index 33115c11..8b49f6c6 100644 --- a/firmware/targets/furi_hal_include/furi_hal_usb.h +++ b/firmware/targets/furi_hal_include/furi_hal_usb.h @@ -2,6 +2,10 @@ #include "usb.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct FuriHalUsbInterface FuriHalUsbInterface; struct FuriHalUsbInterface { @@ -81,3 +85,7 @@ void furi_hal_usb_set_state_callback(FuriHalUsbStateCallback cb, void* ctx); /** Restart USB device */ void furi_hal_usb_reinit(); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/furi_hal_include/furi_hal_usb_hid.h b/firmware/targets/furi_hal_include/furi_hal_usb_hid.h index 97bac7f0..f4b40c89 100644 --- a/firmware/targets/furi_hal_include/furi_hal_usb_hid.h +++ b/firmware/targets/furi_hal_include/furi_hal_usb_hid.h @@ -5,6 +5,10 @@ #include "hid_usage_consumer.h" #include "hid_usage_led.h" +#ifdef __cplusplus +extern "C" { +#endif + #define HID_KEYBOARD_NONE 0x00 // Remapping the colon key which is shift + ; to comma #define HID_KEYBOARD_COMMA HID_KEYBOARD_COLON @@ -251,3 +255,7 @@ bool furi_hal_hid_consumer_key_press(uint16_t button); * @param button key code */ bool furi_hal_hid_consumer_key_release(uint16_t button); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h b/firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h index e9bf5765..1b20a33c 100644 --- a/firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h +++ b/firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h @@ -1,5 +1,9 @@ #pragma once +#ifdef __cplusplus +extern "C" { +#endif + #define HID_U2F_PACKET_LEN 64 typedef enum { @@ -34,3 +38,7 @@ uint32_t furi_hal_hid_u2f_get_request(uint8_t* data); * @param len packet length */ void furi_hal_hid_u2f_send_response(uint8_t* data, uint8_t len); + +#ifdef __cplusplus +} +#endif diff --git a/furi/core/core_defines.h b/furi/core/core_defines.h index 801810f6..487fe2ca 100644 --- a/furi/core/core_defines.h +++ b/furi/core/core_defines.h @@ -85,7 +85,11 @@ extern "C" { #endif #ifndef FURI_BIT_SET -#define FURI_BIT_SET(x, n) ((x) |= (1 << (n))) +#define FURI_BIT_SET(x, n) \ + ({ \ + __typeof__(x) _x = (1); \ + (x) |= (_x << (n)); \ + }) #endif #ifndef FURI_BIT_CLEAR diff --git a/furi/core/memmgr.c b/furi/core/memmgr.c index dba1a707..768adc05 100644 --- a/furi/core/memmgr.c +++ b/furi/core/memmgr.c @@ -92,4 +92,20 @@ size_t memmgr_pool_get_free(void) { size_t memmgr_pool_get_max_block(void) { return furi_hal_memory_max_pool_block(); +} + +void* aligned_malloc(size_t size, size_t alignment) { + void* p1; // original block + void** p2; // aligned block + int offset = alignment - 1 + sizeof(void*); + if((p1 = (void*)malloc(size + offset)) == NULL) { + return NULL; + } + p2 = (void**)(((size_t)(p1) + offset) & ~(alignment - 1)); + p2[-1] = p1; + return p2; +} + +void aligned_free(void* p) { + free(((void**)p)[-1]); } \ No newline at end of file diff --git a/furi/core/memmgr.h b/furi/core/memmgr.h index fdecfd72..d3ad0c87 100644 --- a/furi/core/memmgr.h +++ b/furi/core/memmgr.h @@ -35,6 +35,21 @@ size_t memmgr_get_total_heap(void); */ size_t memmgr_get_minimum_free_heap(void); +/** + * An aligned version of malloc, used when you need to get the aligned space on the heap + * Freeing the received address is performed ONLY through the aligned_free function + * @param size + * @param alignment + * @return void* + */ +void* aligned_malloc(size_t size, size_t alignment); + +/** + * Freed space obtained through the aligned_malloc function + * @param p pointer to result of aligned_malloc + */ +void aligned_free(void* p); + /** * @brief Allocate memory from separate memory pool. That memory can't be freed. * diff --git a/furi/core/thread.c b/furi/core/thread.c index a68472b5..58cb9bc0 100644 --- a/furi/core/thread.c +++ b/furi/core/thread.c @@ -89,7 +89,9 @@ static void furi_thread_body(void* context) { if(thread->is_service) { FURI_LOG_E( - "Service", "%s thread exited. Thread memory cannot be reclaimed.", thread->name); + "Service", + "%s thread exited. Thread memory cannot be reclaimed.", + thread->name ? thread->name : ""); } // clear thread local storage @@ -515,4 +517,23 @@ size_t furi_thread_stdout_write(const char* data, size_t size) { int32_t furi_thread_stdout_flush() { return __furi_thread_stdout_flush(furi_thread_get_current()); -} \ No newline at end of file +} + +void furi_thread_suspend(FuriThreadId thread_id) { + TaskHandle_t hTask = (TaskHandle_t)thread_id; + vTaskSuspend(hTask); +} + +void furi_thread_resume(FuriThreadId thread_id) { + TaskHandle_t hTask = (TaskHandle_t)thread_id; + if(FURI_IS_IRQ_MODE()) { + xTaskResumeFromISR(hTask); + } else { + vTaskResume(hTask); + } +} + +bool furi_thread_is_suspended(FuriThreadId thread_id) { + TaskHandle_t hTask = (TaskHandle_t)thread_id; + return eTaskGetState(hTask) == eSuspended; +} diff --git a/furi/core/thread.h b/furi/core/thread.h index f15b9ff6..fda81bb3 100644 --- a/furi/core/thread.h +++ b/furi/core/thread.h @@ -236,6 +236,25 @@ size_t furi_thread_stdout_write(const char* data, size_t size); */ int32_t furi_thread_stdout_flush(); +/** Suspend thread + * + * @param thread_id thread id + */ +void furi_thread_suspend(FuriThreadId thread_id); + +/** Resume thread + * + * @param thread_id thread id + */ +void furi_thread_resume(FuriThreadId thread_id); + +/** Get thread suspended state + * + * @param thread_id thread id + * @return true if thread is suspended + */ +bool furi_thread_is_suspended(FuriThreadId thread_id); + #ifdef __cplusplus } #endif diff --git a/furi/core/timer.c b/furi/core/timer.c index 807f477e..462a2e89 100644 --- a/furi/core/timer.c +++ b/furi/core/timer.c @@ -1,5 +1,7 @@ #include "timer.h" #include "check.h" +#include "memmgr.h" +#include "kernel.h" #include "core/common_defines.h" #include @@ -39,7 +41,7 @@ FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* co /* Dynamic memory allocation is available: if memory for callback and */ /* its context is not provided, allocate it from dynamic memory pool */ if(callb == NULL) { - callb = (TimerCallback_t*)pvPortMalloc(sizeof(TimerCallback_t)); + callb = (TimerCallback_t*)malloc(sizeof(TimerCallback_t)); if(callb != NULL) { /* Callback memory was allocated from dynamic pool, set flag */ @@ -65,7 +67,7 @@ FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* co if((hTimer == NULL) && (callb != NULL) && (callb_dyn == 1U)) { /* Failed to create a timer, release allocated resources */ callb = (TimerCallback_t*)((uint32_t)callb & ~1U); - vPortFree(callb); + free(callb); } } @@ -82,14 +84,16 @@ void furi_timer_free(FuriTimer* instance) { callb = (TimerCallback_t*)pvTimerGetTimerID(hTimer); - if(xTimerDelete(hTimer, portMAX_DELAY) == pdPASS) { - if((uint32_t)callb & 1U) { - /* Callback memory was allocated from dynamic pool, clear flag */ - callb = (TimerCallback_t*)((uint32_t)callb & ~1U); + furi_check(xTimerDelete(hTimer, portMAX_DELAY) == pdPASS); - /* Return allocated memory to dynamic pool */ - vPortFree(callb); - } + while (furi_timer_is_running(instance)) furi_delay_tick(2); + + if((uint32_t)callb & 1U) { + /* Callback memory was allocated from dynamic pool, clear flag */ + callb = (TimerCallback_t*)((uint32_t)callb & ~1U); + + /* Return allocated memory to dynamic pool */ + free(callb); } } @@ -120,11 +124,8 @@ FuriStatus furi_timer_stop(FuriTimer* instance) { if(xTimerIsTimerActive(hTimer) == pdFALSE) { stat = FuriStatusErrorResource; } else { - if(xTimerStop(hTimer, portMAX_DELAY) == pdPASS) { - stat = FuriStatusOk; - } else { - stat = FuriStatusError; - } + furi_check(xTimerStop(hTimer, portMAX_DELAY) == pdPASS); + stat = FuriStatusOk; } /* Return execution status */ diff --git a/lib/SConscript b/lib/SConscript index 4498c4c9..2822684b 100644 --- a/lib/SConscript +++ b/lib/SConscript @@ -15,7 +15,15 @@ env.Append( "lib/u8g2", "lib/update_util", "lib/print", - ] + ], + SDK_HEADERS=[ + File("#/lib/one_wire/one_wire_host_timing.h"), + File("#/lib/one_wire/one_wire_host.h"), + File("#/lib/one_wire/one_wire_slave.h"), + File("#/lib/one_wire/one_wire_device.h"), + File("#/lib/one_wire/ibutton/ibutton_worker.h"), + File("#/lib/one_wire/maxim_crc.h"), + ], ) env.Append( @@ -24,7 +32,7 @@ env.Append( "#/lib", # TODO: remove! "#/lib/mlib", # Ugly hack - "${BUILD_DIR}/assets/compiled", + Dir("../assets/compiled"), ], CPPDEFINES=[ '"M_MEMORY_FULL(x)=abort()"', @@ -76,8 +84,8 @@ libs = env.BuildModules( "nfc", "appframe", "misc", - "loclass", "lfrfid", + "flipper_application", ], ) diff --git a/lib/ST25RFAL002/include/rfal_picopass.h b/lib/ST25RFAL002/include/rfal_picopass.h deleted file mode 100644 index e7fb272c..00000000 --- a/lib/ST25RFAL002/include/rfal_picopass.h +++ /dev/null @@ -1,64 +0,0 @@ - -#ifndef RFAL_PICOPASS_H -#define RFAL_PICOPASS_H - -/* - ****************************************************************************** - * INCLUDES - ****************************************************************************** - */ -#include "platform.h" -#include "rfal_rf.h" -#include "rfal_crc.h" -#include "st_errno.h" - -#define RFAL_PICOPASS_UID_LEN 8 -#define RFAL_PICOPASS_MAX_BLOCK_LEN 8 - -#define RFAL_PICOPASS_TXRX_FLAGS \ - (RFAL_TXRX_FLAGS_CRC_TX_MANUAL | RFAL_TXRX_FLAGS_AGC_ON | RFAL_TXRX_FLAGS_PAR_RX_REMV | \ - RFAL_TXRX_FLAGS_CRC_RX_KEEP) - -enum { - RFAL_PICOPASS_CMD_ACTALL = 0x0A, - RFAL_PICOPASS_CMD_IDENTIFY = 0x0C, - RFAL_PICOPASS_CMD_SELECT = 0x81, - RFAL_PICOPASS_CMD_READCHECK = 0x88, - RFAL_PICOPASS_CMD_CHECK = 0x05, - RFAL_PICOPASS_CMD_READ = 0x0C, - RFAL_PICOPASS_CMD_WRITE = 0x87, -}; - -typedef struct { - uint8_t CSN[RFAL_PICOPASS_UID_LEN]; // Anti-collision CSN - uint8_t crc[2]; -} rfalPicoPassIdentifyRes; - -typedef struct { - uint8_t CSN[RFAL_PICOPASS_UID_LEN]; // Real CSN - uint8_t crc[2]; -} rfalPicoPassSelectRes; - -typedef struct { - uint8_t CCNR[8]; -} rfalPicoPassReadCheckRes; - -typedef struct { - uint8_t mac[4]; -} rfalPicoPassCheckRes; - -typedef struct { - uint8_t data[RFAL_PICOPASS_MAX_BLOCK_LEN]; - uint8_t crc[2]; -} rfalPicoPassReadBlockRes; - -ReturnCode rfalPicoPassPollerInitialize(void); -ReturnCode rfalPicoPassPollerCheckPresence(void); -ReturnCode rfalPicoPassPollerIdentify(rfalPicoPassIdentifyRes* idRes); -ReturnCode rfalPicoPassPollerSelect(uint8_t* csn, rfalPicoPassSelectRes* selRes); -ReturnCode rfalPicoPassPollerReadCheck(rfalPicoPassReadCheckRes* rcRes); -ReturnCode rfalPicoPassPollerCheck(uint8_t* mac, rfalPicoPassCheckRes* chkRes); -ReturnCode rfalPicoPassPollerReadBlock(uint8_t blockNum, rfalPicoPassReadBlockRes* readRes); -ReturnCode rfalPicoPassPollerWriteBlock(uint8_t blockNum, uint8_t data[8], uint8_t mac[4]); - -#endif /* RFAL_PICOPASS_H */ diff --git a/lib/STM32CubeWB.scons b/lib/STM32CubeWB.scons index 80d06b5f..e8350ea9 100644 --- a/lib/STM32CubeWB.scons +++ b/lib/STM32CubeWB.scons @@ -13,6 +13,11 @@ env.Append( "USE_FULL_ASSERT", "USE_FULL_LL_DRIVER", ], + SDK_HEADERS=env.GlobRecursive( + "*_ll_*.h", + "#/lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/", + exclude="*usb.h", + ), ) if env["RAM_EXEC"]: diff --git a/lib/app-scened-template/generic_scene.hpp b/lib/app-scened-template/generic_scene.hpp index 979e9747..bcdf0b46 100644 --- a/lib/app-scened-template/generic_scene.hpp +++ b/lib/app-scened-template/generic_scene.hpp @@ -1,4 +1,5 @@ -template class GenericScene { +template +class GenericScene { public: virtual void on_enter(TApp* app, bool need_restore) = 0; virtual bool on_event(TApp* app, typename TApp::Event* event) = 0; diff --git a/lib/app-scened-template/record_controller.hpp b/lib/app-scened-template/record_controller.hpp index 9b14274a..171115e1 100644 --- a/lib/app-scened-template/record_controller.hpp +++ b/lib/app-scened-template/record_controller.hpp @@ -6,7 +6,8 @@ * * @tparam TRecordClass record class */ -template class RecordController { +template +class RecordController { public: /** * @brief Construct a new Record Controller object for record with record name diff --git a/lib/app-scened-template/scene_controller.hpp b/lib/app-scened-template/scene_controller.hpp index 678f6c0d..052eca73 100644 --- a/lib/app-scened-template/scene_controller.hpp +++ b/lib/app-scened-template/scene_controller.hpp @@ -11,7 +11,8 @@ * @tparam TScene generic scene class * @tparam TApp application class */ -template class SceneController { +template +class SceneController { public: /** * @brief Add scene to scene container diff --git a/lib/app-scened-template/typeindex_no_rtti.hpp b/lib/app-scened-template/typeindex_no_rtti.hpp index 4ac52725..0f399385 100644 --- a/lib/app-scened-template/typeindex_no_rtti.hpp +++ b/lib/app-scened-template/typeindex_no_rtti.hpp @@ -33,12 +33,14 @@ namespace ext { /** * Dummy type for tag-dispatching. */ -template struct tag_type {}; +template +struct tag_type {}; /** * A value of tag_type. */ -template constexpr tag_type tag{}; +template +constexpr tag_type tag{}; /** * A type_index implementation without RTTI. @@ -47,7 +49,8 @@ struct type_index { /** * Creates a type_index object for the specified type. */ - template type_index(tag_type) noexcept : hash_code_{index} { + template + type_index(tag_type) noexcept : hash_code_{index} { } /** @@ -61,7 +64,8 @@ private: /** * Unique integral index associated to template type argument. */ - template static std::size_t const index; + template + static std::size_t const index; /** * Global counter for generating index values. @@ -75,14 +79,16 @@ private: std::size_t hash_code_; }; -template std::size_t const type_index::index = type_index::counter()++; +template +std::size_t const type_index::index = type_index::counter()++; /** * Creates a type_index object for the specified type. * * Equivalent to `ext::type_index{ext::tag}`. */ -template type_index make_type_index() noexcept { +template +type_index make_type_index() noexcept { return tag; } @@ -111,7 +117,8 @@ inline bool operator>=(type_index const& a, type_index const& b) noexcept { } } -template <> struct std::hash { +template <> +struct std::hash { using argument_type = ext::type_index; using result_type = std::size_t; diff --git a/lib/app-scened-template/view_controller.hpp b/lib/app-scened-template/view_controller.hpp index 15028f53..8c48fcf7 100644 --- a/lib/app-scened-template/view_controller.hpp +++ b/lib/app-scened-template/view_controller.hpp @@ -12,7 +12,8 @@ * @tparam TApp application class * @tparam TViewModules variadic list of ViewModules */ -template class ViewController { +template +class ViewController { public: ViewController() { event_queue = furi_message_queue_alloc(10, sizeof(typename TApp::Event)); @@ -44,7 +45,8 @@ public: * @tparam T Concrete ViewModule class * @return T* ViewModule pointer */ - template T* get() { + template + T* get() { uint32_t view_index = ext::make_type_index().hash_code(); furi_check(holder.count(view_index) != 0); return static_cast(holder[view_index]); @@ -56,7 +58,8 @@ public: * @tparam T Concrete ViewModule class * @return T* ViewModule pointer */ - template operator T*() { + template + operator T*() { uint32_t view_index = ext::make_type_index().hash_code(); furi_check(holder.count(view_index) != 0); return static_cast(holder[view_index]); @@ -68,7 +71,8 @@ public: * @tparam T Concrete ViewModule class * @return T* ViewModule pointer */ - template void switch_to() { + template + void switch_to() { uint32_t view_index = ext::make_type_index().hash_code(); furi_check(holder.count(view_index) != 0); view_dispatcher_switch_to_view(view_dispatcher, view_index); diff --git a/lib/cxxheaderparser b/lib/cxxheaderparser new file mode 160000 index 00000000..ba422256 --- /dev/null +++ b/lib/cxxheaderparser @@ -0,0 +1 @@ +Subproject commit ba4222560fc1040670b1a917d5d357198e8ec5d6 diff --git a/lib/digital_signal/digital_signal.h b/lib/digital_signal/digital_signal.h index d828444c..90905d74 100644 --- a/lib/digital_signal/digital_signal.h +++ b/lib/digital_signal/digital_signal.h @@ -6,6 +6,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { bool start_level; uint32_t edge_cnt; @@ -29,3 +33,7 @@ uint32_t digital_signal_get_edges_cnt(DigitalSignal* signal); uint32_t digital_signal_get_edge(DigitalSignal* signal, uint32_t edge_num); void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio); + +#ifdef __cplusplus +} +#endif diff --git a/lib/flipper_application/SConscript b/lib/flipper_application/SConscript new file mode 100644 index 00000000..3a5e7f4d --- /dev/null +++ b/lib/flipper_application/SConscript @@ -0,0 +1,20 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/flipper_application", + ], + SDK_HEADERS=[ + File("#/lib/flipper_application/flipper_application.h"), + ], +) + + +libenv = env.Clone(FW_LIB_NAME="flipper_application") +libenv.ApplyLibFlags() + +sources = libenv.GlobRecursive("*.c") + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/flipper_application/application_manifest.h b/lib/flipper_application/application_manifest.h new file mode 100644 index 00000000..6aa20e48 --- /dev/null +++ b/lib/flipper_application/application_manifest.h @@ -0,0 +1,45 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define FAP_MANIFEST_MAGIC 0x52474448 +#define FAP_MANIFEST_SUPPORTED_VERSION 1 + +#define FAP_MANIFEST_MAX_APP_NAME_LENGTH 32 +#define FAP_MANIFEST_MAX_ICON_SIZE 32 // TODO: reduce size? + +#pragma pack(push, 1) + +typedef struct { + uint32_t manifest_magic; + uint32_t manifest_version; + union { + struct { + uint16_t minor; + uint16_t major; + }; + uint32_t version; + } api_version; + uint16_t hardware_target_id; +} FlipperApplicationManifestBase; + +typedef struct { + FlipperApplicationManifestBase base; + uint16_t stack_size; + uint32_t app_version; + char name[FAP_MANIFEST_MAX_APP_NAME_LENGTH]; + char has_icon; + char icon[FAP_MANIFEST_MAX_ICON_SIZE]; +} FlipperApplicationManifestV1; + +typedef FlipperApplicationManifestV1 FlipperApplicationManifest; + +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif diff --git a/lib/flipper_application/elf/elf.h b/lib/flipper_application/elf/elf.h new file mode 100644 index 00000000..f1697ba4 --- /dev/null +++ b/lib/flipper_application/elf/elf.h @@ -0,0 +1,1148 @@ +#ifndef _ELF_H +#define _ELF_H 1 + +/* Standard ELF types. */ + +#include + +/* Type for a 16-bit quantity. */ +typedef uint16_t Elf32_Half; +typedef uint16_t Elf64_Half; + +/* Types for signed and unsigned 32-bit quantities. */ +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; + +/* Types for signed and unsigned 64-bit quantities. */ +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* Type of addresses. */ +typedef uint32_t Elf32_Addr; +typedef uint64_t Elf64_Addr; + +/* Type of file offsets. */ +typedef uint32_t Elf32_Off; +typedef uint64_t Elf64_Off; + +/* Type for section indices, which are 16-bit quantities. */ +typedef uint16_t Elf32_Section; +typedef uint16_t Elf64_Section; + +/* Type for version symbol information. */ +typedef Elf32_Half Elf32_Versym; +typedef Elf64_Half Elf64_Versym; + +/* The ELF file header. This appears at the start of every ELF file. */ + +#define EI_NIDENT (16) + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Architecture */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size in bytes */ + Elf64_Half e_phentsize; /* Program header table entry size */ + Elf64_Half e_phnum; /* Program header table entry count */ + Elf64_Half e_shentsize; /* Section header table entry size */ + Elf64_Half e_shnum; /* Section header table entry count */ + Elf64_Half e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + +/* Fields in the e_ident array. The EI_* macros are indices into the + array. The macros under each EI_* macro are the values the byte + may have. */ + +#define EI_MAG0 0 /* File identification byte 0 index */ +#define ELFMAG0 0x7f /* Magic number byte 0 */ + +#define EI_MAG1 1 /* File identification byte 1 index */ +#define ELFMAG1 'E' /* Magic number byte 1 */ + +#define EI_MAG2 2 /* File identification byte 2 index */ +#define ELFMAG2 'L' /* Magic number byte 2 */ + +#define EI_MAG3 3 /* File identification byte 3 index */ +#define ELFMAG3 'F' /* Magic number byte 3 */ + +/* Conglomeration of the identification bytes, for easy testing as a word. */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ +#define ELFCLASSNUM 3 + +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ +#define ELFDATANUM 3 + +#define EI_VERSION 6 /* File version byte index */ +/* Value must be EV_CURRENT */ + +#define EI_OSABI 7 /* OS ABI identification */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_SYSV 0 /* Alias. */ +#define ELFOSABI_HPUX 1 /* HP-UX */ +#define ELFOSABI_NETBSD 2 /* NetBSD. */ +#define ELFOSABI_LINUX 3 /* Linux. */ +#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ +#define ELFOSABI_AIX 7 /* IBM AIX. */ +#define ELFOSABI_IRIX 8 /* SGI Irix. */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ +#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define EI_ABIVERSION 8 /* ABI version */ + +#define EI_PAD 9 /* Byte index of padding bytes */ + +/* Legal values for e_type (object file type). */ + +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_NUM 5 /* Number of defined types */ +#define ET_LOOS 0xfe00 /* OS-specific range start */ +#define ET_HIOS 0xfeff /* OS-specific range end */ +#define ET_LOPROC 0xff00 /* Processor-specific range start */ +#define ET_HIPROC 0xffff /* Processor-specific range end */ + +/* Legal values for e_machine (architecture). */ + +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SUN SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola m68k family */ +#define EM_88K 5 /* Motorola m88k family */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 big-endian */ +#define EM_S370 9 /* IBM System/370 */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ + +#define EM_PARISC 15 /* HPPA */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64-bit */ +#define EM_S390 22 /* IBM S390 */ + +#define EM_V800 36 /* NEC V800 series */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_RCE 39 /* Motorola RCE */ +#define EM_ARM 40 /* ARM */ +#define EM_FAKE_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Hitachi SH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_TRICORE 44 /* Siemens Tricore */ +#define EM_ARC 45 /* Argonaut RISC Core */ +#define EM_H8_300 46 /* Hitachi H8/300 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +#define EM_H8_500 49 /* Hitachi H8/500 */ +#define EM_IA_64 50 /* Intel Merced */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Start*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_PDSP 63 /* Sony DSP Processor */ + +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ +#define EM_HUANY 81 /* Harvard University machine-independent object files */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Mitsubishi M32R */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_NUM 95 + +/* Legal values for e_version (version). */ + +#define EV_NONE 0 /* Invalid ELF version */ +#define EV_CURRENT 1 /* Current version */ +#define EV_NUM 2 + +/* Section header. */ + +typedef struct { + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; + +typedef struct { + Elf64_Word sh_name; /* Section name (string tbl index) */ + Elf64_Word sh_type; /* Section type */ + Elf64_Xword sh_flags; /* Section flags */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Section size in bytes */ + Elf64_Word sh_link; /* Link to another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +/* Special section indices. */ + +#define SHN_UNDEF 0 /* Undefined section */ +#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ +#define SHN_LOPROC 0xff00 /* Start of processor-specific */ +#define SHN_BEFORE \ + 0xff00 /* Order section before all others + (Solaris). */ +#define SHN_AFTER \ + 0xff01 /* Order section after all others + (Solaris). */ +#define SHN_HIPROC 0xff1f /* End of processor-specific */ +#define SHN_LOOS 0xff20 /* Start of OS-specific */ +#define SHN_HIOS 0xff3f /* End of OS-specific */ +#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ +#define SHN_COMMON 0xfff2 /* Associated symbol is common */ +#define SHN_XINDEX 0xffff /* Index is in extra table. */ +#define SHN_HIRESERVE 0xffff /* End of reserved indices */ + +/* Legal values for sh_type (section type). */ + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* Number of defined types. */ +#define SHT_LOOS 0x60000000 /* Start OS-specific. */ +#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ +#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ +#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ +#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +#define SHT_HIUSER 0x8fffffff /* End of application-specific */ + +/* Legal values for sh_flags (section flags). */ + +#define SHF_WRITE (1 << 0) /* Writable */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MERGE (1 << 4) /* Might be merged */ +#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ +#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ +#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ +#define SHF_OS_NONCONFORMING \ + (1 << 8) /* Non-standard OS specific handling + required */ +#define SHF_GROUP (1 << 9) /* Section is member of a group. */ +#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ +#define SHF_ORDERED \ + (1 << 30) /* Special ordering requirement + (Solaris). */ +#define SHF_EXCLUDE \ + (1 << 31) /* Section is excluded unless + referenced or allocated (Solaris).*/ + +/* Section group handling. */ +#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ + +/* Symbol table entry. */ + +typedef struct { + Elf32_Word st_name; /* Symbol name (string tbl index) */ + Elf32_Addr st_value; /* Symbol value */ + Elf32_Word st_size; /* Symbol size */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf32_Section st_shndx; /* Section index */ +} Elf32_Sym; + +typedef struct { + Elf64_Word st_name; /* Symbol name (string tbl index) */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf64_Section st_shndx; /* Section index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Symbol size */ +} Elf64_Sym; + +/* The syminfo section if available contains additional information about + every dynamic symbol. */ + +typedef struct { + Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf32_Half si_flags; /* Per symbol flags */ +} Elf32_Syminfo; + +typedef struct { + Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf64_Half si_flags; /* Per symbol flags */ +} Elf64_Syminfo; + +/* Possible values for si_boundto. */ +#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ + +/* Possible bitmasks for si_flags. */ +#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ +#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD \ + 0x0008 /* Symbol bound to object to be lazy + loaded */ +/* Syminfo version values. */ +#define SYMINFO_NONE 0 +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* How to extract and insert information held in the st_info field. */ + +#define ELF32_ST_BIND(val) (((unsigned char)(val)) >> 4) +#define ELF32_ST_TYPE(val) ((val)&0xf) +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type)&0xf)) + +/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ +#define ELF64_ST_BIND(val) ELF32_ST_BIND(val) +#define ELF64_ST_TYPE(val) ELF32_ST_TYPE(val) +#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO((bind), (type)) + +/* Legal values for ST_BIND subfield of st_info (symbol binding). */ + +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* Weak symbol */ +#define STB_NUM 3 /* Number of defined types. */ +#define STB_LOOS 10 /* Start of OS-specific */ +#define STB_GNU_UNIQUE 10 /* Unique symbol. */ +#define STB_HIOS 12 /* End of OS-specific */ +#define STB_LOPROC 13 /* Start of processor-specific */ +#define STB_HIPROC 15 /* End of processor-specific */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_NOTYPE 0 /* Symbol type is unspecified */ +#define STT_OBJECT 1 /* Symbol is a data object */ +#define STT_FUNC 2 /* Symbol is a code object */ +#define STT_SECTION 3 /* Symbol associated with a section */ +#define STT_FILE 4 /* Symbol's name is file name */ +#define STT_COMMON 5 /* Symbol is a common data object */ +#define STT_TLS 6 /* Symbol is thread-local data object*/ +#define STT_NUM 7 /* Number of defined types. */ +#define STT_LOOS 10 /* Start of OS-specific */ +#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */ +#define STT_HIOS 12 /* End of OS-specific */ +#define STT_LOPROC 13 /* Start of processor-specific */ +#define STT_HIPROC 15 /* End of processor-specific */ + +/* Symbol table indices are found in the hash buckets and chain table + of a symbol hash table section. This special index value indicates + the end of a chain, meaning no further symbols are found in that bucket. */ + +#define STN_UNDEF 0 /* End of a chain. */ + +/* How to extract and insert information held in the st_other field. */ + +#define ELF32_ST_VISIBILITY(o) ((o)&0x03) + +/* For ELF64 the definitions are the same. */ +#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY(o) + +/* Symbol visibility specification encoded in the st_other field. */ +#define STV_DEFAULT 0 /* Default symbol visibility rules */ +#define STV_INTERNAL 1 /* Processor specific hidden class */ +#define STV_HIDDEN 2 /* Sym unavailable in other modules */ +#define STV_PROTECTED 3 /* Not preemptible, not exported */ + +/* Relocation table entry without addend (in section of type SHT_REL). */ + +typedef struct { + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ +} Elf32_Rel; + +/* I have seen two different definitions of the Elf64_Rel and + Elf64_Rela structures, so we'll leave them out until Novell (or + whoever) gets their act together. */ +/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ + +typedef struct { + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ +} Elf64_Rel; + +/* Relocation table entry with addend (in section of type SHT_RELA). */ + +typedef struct { + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ + Elf32_Sword r_addend; /* Addend */ +} Elf32_Rela; + +typedef struct { + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ + Elf64_Sxword r_addend; /* Addend */ +} Elf64_Rela; + +/* How to extract and insert information held in the r_info field. */ + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val)&0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type)&0xff)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i)&0xffffffff) +#define ELF64_R_INFO(sym, type) ((((Elf64_Xword)(sym)) << 32) + (type)) + +/* Program segment header. */ + +typedef struct { + Elf32_Word p_type; /* Segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment */ +} Elf32_Phdr; + +typedef struct { + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ +} Elf64_Phdr; + +/* Legal values for p_type (segment type). */ + +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_TLS 7 /* Thread-local storage segment */ +#define PT_NUM 8 /* Number of defined types */ +#define PT_LOOS 0x60000000 /* Start of OS-specific */ +#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ +#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* End of OS-specific */ +#define PT_LOPROC 0x70000000 /* Start of processor-specific */ +#define PT_HIPROC 0x7fffffff /* End of processor-specific */ + +/* Legal values for p_flags (segment flags). */ + +#define PF_X (1 << 0) /* Segment is executable */ +#define PF_W (1 << 1) /* Segment is writable */ +#define PF_R (1 << 2) /* Segment is readable */ +#define PF_MASKOS 0x0ff00000 /* OS-specific */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific */ + +/* Legal values for note segment descriptor types for core files. */ + +#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ +#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ +#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ +#define NT_PRXREG 4 /* Contains copy of prxregset struct */ +#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ +#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ +#define NT_AUXV 6 /* Contains copy of auxv array */ +#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ +#define NT_ASRS 8 /* Contains copy of asrset struct */ +#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ +#define NT_PSINFO 13 /* Contains copy of psinfo struct */ +#define NT_PRCRED 14 /* Contains copy of prcred struct */ +#define NT_UTSNAME 15 /* Contains copy of utsname struct */ +#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ +#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ +#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct */ +#define NT_PRXFPREG 0x46e62b7f /* Contains copy of user_fxsr_struct */ +#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ +#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */ +#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ +#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ +#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ + +/* Legal values for the note segment descriptor types for object files. */ + +#define NT_VERSION 1 /* Contains a version string. */ + +/* Dynamic section entry. */ + +typedef struct { + Elf32_Sword d_tag; /* Dynamic entry type */ + union { + Elf32_Word d_val; /* Integer value */ + Elf32_Addr d_ptr; /* Address value */ + } d_un; +} Elf32_Dyn; + +typedef struct { + Elf64_Sxword d_tag; /* Dynamic entry type */ + union { + Elf64_Xword d_val; /* Integer value */ + Elf64_Addr d_ptr; /* Address value */ + } d_un; +} Elf64_Dyn; + +/* Legal values for d_tag (dynamic entry type). */ + +#define DT_NULL 0 /* Marks end of dynamic section */ +#define DT_NEEDED 1 /* Name of needed library */ +#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ +#define DT_PLTGOT 3 /* Processor defined value */ +#define DT_HASH 4 /* Address of symbol hash table */ +#define DT_STRTAB 5 /* Address of string table */ +#define DT_SYMTAB 6 /* Address of symbol table */ +#define DT_RELA 7 /* Address of Rela relocs */ +#define DT_RELASZ 8 /* Total size of Rela relocs */ +#define DT_RELAENT 9 /* Size of one Rela reloc */ +#define DT_STRSZ 10 /* Size of string table */ +#define DT_SYMENT 11 /* Size of one symbol table entry */ +#define DT_INIT 12 /* Address of init function */ +#define DT_FINI 13 /* Address of termination function */ +#define DT_SONAME 14 /* Name of shared object */ +#define DT_RPATH 15 /* Library search path (deprecated) */ +#define DT_SYMBOLIC 16 /* Start symbol search here */ +#define DT_REL 17 /* Address of Rel relocs */ +#define DT_RELSZ 18 /* Total size of Rel relocs */ +#define DT_RELENT 19 /* Size of one Rel reloc */ +#define DT_PLTREL 20 /* Type of reloc in PLT */ +#define DT_DEBUG 21 /* For debugging; unspecified */ +#define DT_TEXTREL 22 /* Reloc might modify .text */ +#define DT_JMPREL 23 /* Address of PLT relocs */ +#define DT_BIND_NOW 24 /* Process relocations of object */ +#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ +#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ +#define DT_RUNPATH 29 /* Library search path */ +#define DT_FLAGS 30 /* Flags for the object being loaded */ +#define DT_ENCODING 32 /* Start of encoded range */ +#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ +#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ +#define DT_NUM 34 /* Number used */ +#define DT_LOOS 0x6000000d /* Start of OS-specific */ +#define DT_HIOS 0x6ffff000 /* End of OS-specific */ +#define DT_LOPROC 0x70000000 /* Start of processor-specific */ +#define DT_HIPROC 0x7fffffff /* End of processor-specific */ +#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ + +/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's + approach. */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ +#define DT_CHECKSUM 0x6ffffdf8 +#define DT_PLTPADSZ 0x6ffffdf9 +#define DT_MOVEENT 0x6ffffdfa +#define DT_MOVESZ 0x6ffffdfb +#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ +#define DT_POSFLAG_1 \ + 0x6ffffdfd /* Flags for DT_* entries, effecting + the following DT_* entry. */ +#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ +#define DT_VALRNGHI 0x6ffffdff +#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ +#define DT_VALNUM 12 + +/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + + If any adjustment is made to the ELF object after it has been + built these entries will need to be adjusted. */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */ +#define DT_TLSDESC_PLT 0x6ffffef6 +#define DT_TLSDESC_GOT 0x6ffffef7 +#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ +#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ +#define DT_CONFIG 0x6ffffefa /* Configuration information. */ +#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ +#define DT_AUDIT 0x6ffffefc /* Object auditing. */ +#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ +#define DT_MOVETAB 0x6ffffefe /* Move table. */ +#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ +#define DT_ADDRNUM 11 + +/* The versioning entry types. The next are defined as part of the + GNU extension. */ +#define DT_VERSYM 0x6ffffff0 + +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa + +/* These were chosen by Sun. */ +#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ +#define DT_VERDEF \ + 0x6ffffffc /* Address of version definition + table */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ +#define DT_VERNEED \ + 0x6ffffffe /* Address of table with needed + versions */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ +#define DT_VERSIONTAGNUM 16 + +/* Sun added these machine-independent extensions in the "processor-specific" + range. Be compatible. */ +#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ +#define DT_FILTER 0x7fffffff /* Shared object to get values from */ +#define DT_EXTRATAGIDX(tag) ((Elf32_Word) - ((Elf32_Sword)(tag) << 1 >> 1) - 1) +#define DT_EXTRANUM 3 + +/* Values of `d_un.d_val' in the DT_FLAGS entry. */ +#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ +#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ +#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ +#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ +#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ + +/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 + entry in the dynamic section. */ +#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ +#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ +#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ +#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ +#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ +#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ +#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ +#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ +#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ +#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ +#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ +#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ +#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ +#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ +#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ + +/* Flags for the feature selection in DT_FEATURE_1. */ +#define DTF_1_PARINIT 0x00000001 +#define DTF_1_CONFEXP 0x00000002 + +/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ +#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ +#define DF_P1_GROUPPERM \ + 0x00000002 /* Symbols from next object are not + generally available. */ + +/* Version definition sections. */ + +typedef struct { + Elf32_Half vd_version; /* Version revision */ + Elf32_Half vd_flags; /* Version information */ + Elf32_Half vd_ndx; /* Version Index */ + Elf32_Half vd_cnt; /* Number of associated aux entries */ + Elf32_Word vd_hash; /* Version name hash value */ + Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf32_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf32_Verdef; + +typedef struct { + Elf64_Half vd_version; /* Version revision */ + Elf64_Half vd_flags; /* Version information */ + Elf64_Half vd_ndx; /* Version Index */ + Elf64_Half vd_cnt; /* Number of associated aux entries */ + Elf64_Word vd_hash; /* Version name hash value */ + Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf64_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf64_Verdef; + +/* Legal values for vd_version (version revision). */ +#define VER_DEF_NONE 0 /* No version */ +#define VER_DEF_CURRENT 1 /* Current version */ +#define VER_DEF_NUM 2 /* Given version number */ + +/* Legal values for vd_flags (version information flags). */ +#define VER_FLG_BASE 0x1 /* Version definition of file itself */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + +/* Versym symbol index values. */ +#define VER_NDX_LOCAL 0 /* Symbol is local. */ +#define VER_NDX_GLOBAL 1 /* Symbol is global. */ +#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ +#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ + +/* Auxialiary version information. */ + +typedef struct { + Elf32_Word vda_name; /* Version or dependency names */ + Elf32_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf32_Verdaux; + +typedef struct { + Elf64_Word vda_name; /* Version or dependency names */ + Elf64_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf64_Verdaux; + +/* Version dependency section. */ + +typedef struct { + Elf32_Half vn_version; /* Version of structure */ + Elf32_Half vn_cnt; /* Number of associated aux entries */ + Elf32_Word vn_file; /* Offset of filename for this + dependency */ + Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf32_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf32_Verneed; + +typedef struct { + Elf64_Half vn_version; /* Version of structure */ + Elf64_Half vn_cnt; /* Number of associated aux entries */ + Elf64_Word vn_file; /* Offset of filename for this + dependency */ + Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf64_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf64_Verneed; + +/* Legal values for vn_version (version revision). */ +#define VER_NEED_NONE 0 /* No version */ +#define VER_NEED_CURRENT 1 /* Current version */ +#define VER_NEED_NUM 2 /* Given version number */ + +/* Auxiliary needed version information. */ + +typedef struct { + Elf32_Word vna_hash; /* Hash value of dependency name */ + Elf32_Half vna_flags; /* Dependency specific information */ + Elf32_Half vna_other; /* Unused */ + Elf32_Word vna_name; /* Dependency name string offset */ + Elf32_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf32_Vernaux; + +typedef struct { + Elf64_Word vna_hash; /* Hash value of dependency name */ + Elf64_Half vna_flags; /* Dependency specific information */ + Elf64_Half vna_other; /* Unused */ + Elf64_Word vna_name; /* Dependency name string offset */ + Elf64_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf64_Vernaux; + +/* Legal values for vna_flags. */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + +/* Auxiliary vector. */ + +/* This vector is normally only used by the program interpreter. The + usual definition in an ABI supplement uses the name auxv_t. The + vector is not usually defined in a standard file, but it + can't hurt. We rename it to avoid conflicts. The sizes of these + types are an arrangement between the exec server and the program + interpreter, so we don't fully specify them here. */ + +typedef struct { + uint32_t a_type; /* Entry type */ + union { + uint32_t a_val; /* Integer value */ + /* We use to have pointer elements added here. We cannot do that, + though, since it does not work when using 32-bit definitions + on 64-bit platforms and vice versa. */ + } a_un; +} Elf32_auxv_t; + +typedef struct { + uint64_t a_type; /* Entry type */ + union { + uint64_t a_val; /* Integer value */ + /* We use to have pointer elements added here. We cannot do that, + though, since it does not work when using 32-bit definitions + on 64-bit platforms and vice versa. */ + } a_un; +} Elf64_auxv_t; + +/* Legal values for a_type (entry type). */ + +#define AT_NULL 0 /* End of vector */ +#define AT_IGNORE 1 /* Entry should be ignored */ +#define AT_EXECFD 2 /* File descriptor of program */ +#define AT_PHDR 3 /* Program headers for program */ +#define AT_PHENT 4 /* Size of program header entry */ +#define AT_PHNUM 5 /* Number of program headers */ +#define AT_PAGESZ 6 /* System page size */ +#define AT_BASE 7 /* Base address of interpreter */ +#define AT_FLAGS 8 /* Flags */ +#define AT_ENTRY 9 /* Entry point of program */ +#define AT_NOTELF 10 /* Program is not ELF */ +#define AT_UID 11 /* Real uid */ +#define AT_EUID 12 /* Effective uid */ +#define AT_GID 13 /* Real gid */ +#define AT_EGID 14 /* Effective gid */ +#define AT_CLKTCK 17 /* Frequency of times() */ + +/* Some more special a_type values describing the hardware. */ +#define AT_PLATFORM 15 /* String identifying platform. */ +#define AT_HWCAP \ + 16 /* Machine dependent hints about + processor capabilities. */ + +/* This entry gives some information about the FPU initialization + performed by the kernel. */ +#define AT_FPUCW 18 /* Used FPU control word. */ + +/* Cache block sizes. */ +#define AT_DCACHEBSIZE 19 /* Data cache block size. */ +#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ +#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ + +/* A special ignored value for PPC, used by the kernel to control the + interpretation of the AUXV. Must be > 16. */ +#define AT_IGNOREPPC 22 /* Entry should be ignored. */ + +#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ + +#define AT_BASE_PLATFORM 24 /* String identifying real platforms.*/ + +#define AT_RANDOM 25 /* Address of 16 random bytes. */ + +#define AT_EXECFN 31 /* Filename of executable. */ + +/* Pointer to the global system page used for system calls and other + nice things. */ +#define AT_SYSINFO 32 +#define AT_SYSINFO_EHDR 33 + +/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains + log2 of line size; mask those to get cache size. */ +#define AT_L1I_CACHESHAPE 34 +#define AT_L1D_CACHESHAPE 35 +#define AT_L2_CACHESHAPE 36 +#define AT_L3_CACHESHAPE 37 + +/* Note section contents. Each entry in the note section begins with + a header of a fixed form. */ + +typedef struct { + Elf32_Word n_namesz; /* Length of the note's name. */ + Elf32_Word n_descsz; /* Length of the note's descriptor. */ + Elf32_Word n_type; /* Type of the note. */ +} Elf32_Nhdr; + +typedef struct { + Elf64_Word n_namesz; /* Length of the note's name. */ + Elf64_Word n_descsz; /* Length of the note's descriptor. */ + Elf64_Word n_type; /* Type of the note. */ +} Elf64_Nhdr; + +/* Known names of notes. */ + +/* Solaris entries in the note section have this name. */ +#define ELF_NOTE_SOLARIS "SUNW Solaris" + +/* Note entries for GNU systems have this name. */ +#define ELF_NOTE_GNU "GNU" + +/* Defined types of notes for Solaris. */ + +/* Value of descriptor (one word) is desired pagesize for the binary. */ +#define ELF_NOTE_PAGESIZE_HINT 1 + +/* Defined note types for GNU systems. */ + +/* ABI information. The descriptor consists of words: + word 0: OS descriptor + word 1: major version of the ABI + word 2: minor version of the ABI + word 3: subminor version of the ABI +*/ +#define NT_GNU_ABI_TAG 1 +#define ELF_NOTE_ABI NT_GNU_ABI_TAG /* Old name. */ + +/* Known OSes. These values can appear in word 0 of an + NT_GNU_ABI_TAG note section entry. */ +#define ELF_NOTE_OS_LINUX 0 +#define ELF_NOTE_OS_GNU 1 +#define ELF_NOTE_OS_SOLARIS2 2 +#define ELF_NOTE_OS_FREEBSD 3 + +/* Synthetic hwcap information. The descriptor begins with two words: + word 0: number of entries + word 1: bitmask of enabled entries + Then follow variable-length entries, one byte followed by a + '\0'-terminated hwcap name string. The byte gives the bit + number to test if enabled, (1U << bit) & bitmask. */ +#define NT_GNU_HWCAP 2 + +/* Build ID bits as generated by ld --build-id. + The descriptor consists of any nonzero number of bytes. */ +#define NT_GNU_BUILD_ID 3 + +/* Version note generated by GNU gold containing a version string. */ +#define NT_GNU_GOLD_VERSION 4 + +/* Move records. */ +typedef struct { + Elf32_Xword m_value; /* Symbol value. */ + Elf32_Word m_info; /* Size and index. */ + Elf32_Word m_poffset; /* Symbol offset. */ + Elf32_Half m_repeat; /* Repeat count. */ + Elf32_Half m_stride; /* Stride info. */ +} Elf32_Move; + +typedef struct { + Elf64_Xword m_value; /* Symbol value. */ + Elf64_Xword m_info; /* Size and index. */ + Elf64_Xword m_poffset; /* Symbol offset. */ + Elf64_Half m_repeat; /* Repeat count. */ + Elf64_Half m_stride; /* Stride info. */ +} Elf64_Move; + +/* Macro to construct move records. */ +#define ELF32_M_SYM(info) ((info) >> 8) +#define ELF32_M_SIZE(info) ((unsigned char)(info)) +#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char)(size)) + +#define ELF64_M_SYM(info) ELF32_M_SYM(info) +#define ELF64_M_SIZE(info) ELF32_M_SIZE(info) +#define ELF64_M_INFO(sym, size) ELF32_M_INFO(sym, size) + +/* ARM specific declarations */ + +/* Processor specific flags for the ELF header e_flags field. */ +#define EF_ARM_RELEXEC 0x01 +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_INTERWORK 0x04 +#define EF_ARM_APCS_26 0x08 +#define EF_ARM_APCS_FLOAT 0x10 +#define EF_ARM_PIC 0x20 +#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ +#define EF_ARM_NEW_ABI 0x80 +#define EF_ARM_OLD_ABI 0x100 +#define EF_ARM_SOFT_FLOAT 0x200 +#define EF_ARM_VFP_FLOAT 0x400 +#define EF_ARM_MAVERICK_FLOAT 0x800 + +/* Other constants defined in the ARM ELF spec. version B-01. */ +/* NB. These conflict with values defined above. */ +#define EF_ARM_SYMSARESORTED 0x04 +#define EF_ARM_DYNSYMSUSESEGIDX 0x08 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_EABIMASK 0XFF000000 + +/* Constants defined in AAELF. */ +#define EF_ARM_BE8 0x00800000 +#define EF_ARM_LE8 0x00400000 + +#define EF_ARM_EABI_VERSION(flags) ((flags)&EF_ARM_EABIMASK) +#define EF_ARM_EABI_UNKNOWN 0x00000000 +#define EF_ARM_EABI_VER1 0x01000000 +#define EF_ARM_EABI_VER2 0x02000000 +#define EF_ARM_EABI_VER3 0x03000000 +#define EF_ARM_EABI_VER4 0x04000000 +#define EF_ARM_EABI_VER5 0x05000000 + +/* Additional symbol types for Thumb. */ +#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ +#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ + +/* ARM-specific values for sh_flags */ +#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ +#define SHF_ARM_COMDEF \ + 0x80000000 /* Section may be multiply defined + in the input to a link step. */ + +/* ARM-specific program header flags */ +#define PF_ARM_SB \ + 0x10000000 /* Segment contains the location + addressed by the static base. */ +#define PF_ARM_PI 0x20000000 /* Position-independent segment. */ +#define PF_ARM_ABS 0x40000000 /* Absolute segment. */ + +/* Processor specific values for the Phdr p_type field. */ +#define PT_ARM_EXIDX (PT_LOPROC + 1) /* ARM unwind segment. */ + +/* Processor specific values for the Shdr sh_type field. */ +#define SHT_ARM_EXIDX (SHT_LOPROC + 1) /* ARM unwind section. */ +#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */ +#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */ + +/* ARM relocs. */ + +#define R_ARM_NONE 0 /* No reloc */ +#define R_ARM_PC24 1 /* PC relative 26 bit branch */ +#define R_ARM_ABS32 2 /* Direct 32 bit */ +#define R_ARM_REL32 3 /* PC relative 32 bit */ +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 /* Direct 16 bit */ +#define R_ARM_ABS12 6 /* Direct 12 bit */ +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 /* Direct 8 bit */ +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ +#define R_ARM_COPY 20 /* Copy symbol at runtime */ +#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ +#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ +#define R_ARM_RELATIVE 23 /* Adjust by program base */ +#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ +#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ +#define R_ARM_GOT32 26 /* 32 bit GOT entry */ +#define R_ARM_PLT32 27 /* 32 bit PLT address */ +#define R_ARM_THM_JUMP24 30 /* Thumb32 ((S + A) | T) - P */ +#define R_ARM_ALU_PCREL_7_0 32 +#define R_ARM_ALU_PCREL_15_8 33 +#define R_ARM_ALU_PCREL_23_15 34 +#define R_ARM_LDR_SBREL_11_0 35 +#define R_ARM_ALU_SBREL_19_12 36 +#define R_ARM_ALU_SBREL_27_20 37 +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_THM_PC11 102 /* thumb unconditional branch */ +#define R_ARM_THM_PC9 103 /* thumb conditional branch */ +#define R_ARM_TLS_GD32 \ + 104 /* PC-rel 32 bit for global dynamic + thread local data */ +#define R_ARM_TLS_LDM32 \ + 105 /* PC-rel 32 bit for local dynamic + thread local data */ +#define R_ARM_TLS_LDO32 \ + 106 /* 32 bit offset relative to TLS + block */ +#define R_ARM_TLS_IE32 \ + 107 /* PC-rel 32 bit for GOT entry of + static TLS block offset */ +#define R_ARM_TLS_LE32 \ + 108 /* 32 bit offset relative to static + TLS block */ +#define R_ARM_RXPC25 249 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS22 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 +/* Keep this the last entry. */ +#define R_ARM_NUM 256 + +#endif /* elf.h */ diff --git a/lib/flipper_application/elf/elf_api_interface.h b/lib/flipper_application/elf/elf_api_interface.h new file mode 100644 index 00000000..505f4f71 --- /dev/null +++ b/lib/flipper_application/elf/elf_api_interface.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +#define ELF_INVALID_ADDRESS 0xFFFFFFFF + +typedef struct { + uint16_t api_version_major; + uint16_t api_version_minor; + bool (*resolver_callback)(const char* name, Elf32_Addr* address); +} ElfApiInterface; diff --git a/lib/flipper_application/flipper_applicaiton_i.c b/lib/flipper_application/flipper_applicaiton_i.c new file mode 100644 index 00000000..a2a069ee --- /dev/null +++ b/lib/flipper_application/flipper_applicaiton_i.c @@ -0,0 +1,477 @@ +#include "flipper_application_i.h" +#include + +#define TAG "fapp-i" + +#define RESOLVER_THREAD_YIELD_STEP 30 + +#define IS_FLAGS_SET(v, m) ((v & m) == m) +#define SECTION_OFFSET(e, n) (e->section_table + n * sizeof(Elf32_Shdr)) +#define SYMBOL_OFFSET(e, n) (e->_table + n * sizeof(Elf32_Shdr)) + +bool flipper_application_load_elf_headers(FlipperApplication* e, const char* path) { + Elf32_Ehdr h; + Elf32_Shdr sH; + + if(!storage_file_open(e->fd, path, FSAM_READ, FSOM_OPEN_EXISTING) || + !storage_file_seek(e->fd, 0, true) || + storage_file_read(e->fd, &h, sizeof(h)) != sizeof(h) || + !storage_file_seek(e->fd, h.e_shoff + h.e_shstrndx * sizeof(sH), true) || + storage_file_read(e->fd, &sH, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr)) { + return false; + } + + e->entry = h.e_entry; + e->sections = h.e_shnum; + e->section_table = h.e_shoff; + e->section_table_strings = sH.sh_offset; + return true; +} + +static bool flipper_application_load_metadata(FlipperApplication* e, Elf32_Shdr* sh) { + if(sh->sh_size < sizeof(e->manifest)) { + return false; + } + + return storage_file_seek(e->fd, sh->sh_offset, true) && + storage_file_read(e->fd, &e->manifest, sh->sh_size) == sh->sh_size; +} + +static bool flipper_application_load_debug_link(FlipperApplication* e, Elf32_Shdr* sh) { + e->state.debug_link_size = sh->sh_size; + e->state.debug_link = malloc(sh->sh_size); + + return storage_file_seek(e->fd, sh->sh_offset, true) && + storage_file_read(e->fd, e->state.debug_link, sh->sh_size) == sh->sh_size; +} + +static FindFlags_t flipper_application_preload_section( + FlipperApplication* e, + Elf32_Shdr* sh, + const char* name, + int n) { + FURI_LOG_D(TAG, "Processing: %s", name); + + const struct { + const char* name; + uint16_t* ptr_section_idx; + FindFlags_t flags; + } lookup_sections[] = { + {".text", &e->text.sec_idx, FoundText}, + {".rodata", &e->rodata.sec_idx, FoundRodata}, + {".data", &e->data.sec_idx, FoundData}, + {".bss", &e->bss.sec_idx, FoundBss}, + {".rel.text", &e->text.rel_sec_idx, FoundRelText}, + {".rel.rodata", &e->rodata.rel_sec_idx, FoundRelRodata}, + {".rel.data", &e->data.rel_sec_idx, FoundRelData}, + }; + + for(size_t i = 0; i < COUNT_OF(lookup_sections); i++) { + if(strcmp(name, lookup_sections[i].name) == 0) { + *lookup_sections[i].ptr_section_idx = n; + return lookup_sections[i].flags; + } + } + + if(strcmp(name, ".symtab") == 0) { + e->symbol_table = sh->sh_offset; + e->symbol_count = sh->sh_size / sizeof(Elf32_Sym); + return FoundSymTab; + } else if(strcmp(name, ".strtab") == 0) { + e->symbol_table_strings = sh->sh_offset; + return FoundStrTab; + } else if(strcmp(name, ".fapmeta") == 0) { + // Load metadata immediately + if(flipper_application_load_metadata(e, sh)) { + return FoundFappManifest; + } + } else if(strcmp(name, ".gnu_debuglink") == 0) { + if(flipper_application_load_debug_link(e, sh)) { + return FoundDebugLink; + } + } + return FoundERROR; +} + +static bool + read_string_from_offset(FlipperApplication* e, off_t offset, char* buffer, size_t buffer_size) { + bool success = false; + + off_t old = storage_file_tell(e->fd); + if(storage_file_seek(e->fd, offset, true) && + (storage_file_read(e->fd, buffer, buffer_size) == buffer_size)) { + success = true; + } + storage_file_seek(e->fd, old, true); + + return success; +} + +static bool read_section_name(FlipperApplication* e, off_t off, char* buf, size_t max) { + return read_string_from_offset(e, e->section_table_strings + off, buf, max); +} + +static bool read_symbol_name(FlipperApplication* e, off_t off, char* buf, size_t max) { + return read_string_from_offset(e, e->symbol_table_strings + off, buf, max); +} + +static bool read_section_header(FlipperApplication* e, int n, Elf32_Shdr* h) { + off_t offset = SECTION_OFFSET(e, n); + return storage_file_seek(e->fd, offset, true) && + storage_file_read(e->fd, h, sizeof(Elf32_Shdr)) == sizeof(Elf32_Shdr); +} + +static bool read_section(FlipperApplication* e, int n, Elf32_Shdr* h, char* name, size_t nlen) { + if(!read_section_header(e, n, h)) { + return false; + } + if(!h->sh_name) { + return true; + } + return read_section_name(e, h->sh_name, name, nlen); +} + +bool flipper_application_load_section_table(FlipperApplication* e) { + furi_check(e->state.mmap_entry_count == 0); + + size_t n; + FindFlags_t found = FoundERROR; + FURI_LOG_D(TAG, "Scan ELF indexs..."); + for(n = 1; n < e->sections; n++) { + Elf32_Shdr section_header; + char name[33] = {0}; + if(!read_section_header(e, n, §ion_header)) { + return false; + } + if(section_header.sh_name && + !read_section_name(e, section_header.sh_name, name, sizeof(name))) { + return false; + } + + FURI_LOG_T(TAG, "Examining section %d %s", n, name); + FindFlags_t section_flags = + flipper_application_preload_section(e, §ion_header, name, n); + found |= section_flags; + if((section_flags & FoundGdbSection) != 0) { + e->state.mmap_entry_count++; + } + if(IS_FLAGS_SET(found, FoundAll)) { + return true; + } + } + + FURI_LOG_D(TAG, "Load symbols done"); + return IS_FLAGS_SET(found, FoundValid); +} + +static const char* type_to_str(int symt) { +#define STRCASE(name) \ + case name: \ + return #name; + switch(symt) { + STRCASE(R_ARM_NONE) + STRCASE(R_ARM_ABS32) + STRCASE(R_ARM_THM_PC22) + STRCASE(R_ARM_THM_JUMP24) + default: + return "R_"; + } +#undef STRCASE +} + +static void relocate_jmp_call(Elf32_Addr relAddr, int type, Elf32_Addr symAddr) { + UNUSED(type); + uint16_t upper_insn = ((uint16_t*)relAddr)[0]; + uint16_t lower_insn = ((uint16_t*)relAddr)[1]; + uint32_t S = (upper_insn >> 10) & 1; + uint32_t J1 = (lower_insn >> 13) & 1; + uint32_t J2 = (lower_insn >> 11) & 1; + + int32_t offset = (S << 24) | /* S -> offset[24] */ + ((~(J1 ^ S) & 1) << 23) | /* J1 -> offset[23] */ + ((~(J2 ^ S) & 1) << 22) | /* J2 -> offset[22] */ + ((upper_insn & 0x03ff) << 12) | /* imm10 -> offset[12:21] */ + ((lower_insn & 0x07ff) << 1); /* imm11 -> offset[1:11] */ + if(offset & 0x01000000) offset -= 0x02000000; + + offset += symAddr - relAddr; + + S = (offset >> 24) & 1; + J1 = S ^ (~(offset >> 23) & 1); + J2 = S ^ (~(offset >> 22) & 1); + + upper_insn = ((upper_insn & 0xf800) | (S << 10) | ((offset >> 12) & 0x03ff)); + ((uint16_t*)relAddr)[0] = upper_insn; + + lower_insn = ((lower_insn & 0xd000) | (J1 << 13) | (J2 << 11) | ((offset >> 1) & 0x07ff)); + ((uint16_t*)relAddr)[1] = lower_insn; +} + +static bool relocate_symbol(Elf32_Addr relAddr, int type, Elf32_Addr symAddr) { + switch(type) { + case R_ARM_ABS32: + *((uint32_t*)relAddr) += symAddr; + FURI_LOG_D(TAG, " R_ARM_ABS32 relocated is 0x%08X", (unsigned int)*((uint32_t*)relAddr)); + break; + case R_ARM_THM_PC22: + case R_ARM_THM_JUMP24: + relocate_jmp_call(relAddr, type, symAddr); + FURI_LOG_D( + TAG, " R_ARM_THM_CALL/JMP relocated is 0x%08X", (unsigned int)*((uint32_t*)relAddr)); + break; + default: + FURI_LOG_D(TAG, " Undefined relocation %d", type); + return false; + } + return true; +} + +static ELFSection_t* section_of(FlipperApplication* e, int index) { + if(e->text.sec_idx == index) { + return &e->text; + } else if(e->data.sec_idx == index) { + return &e->data; + } else if(e->bss.sec_idx == index) { + return &e->bss; + } else if(e->rodata.sec_idx == index) { + return &e->rodata; + } + return NULL; +} + +static Elf32_Addr address_of(FlipperApplication* e, Elf32_Sym* sym, const char* sName) { + if(sym->st_shndx == SHN_UNDEF) { + Elf32_Addr addr = 0; + if(e->api_interface->resolver_callback(sName, &addr)) { + return addr; + } + } else { + ELFSection_t* symSec = section_of(e, sym->st_shndx); + if(symSec) { + return ((Elf32_Addr)symSec->data) + sym->st_value; + } + } + FURI_LOG_D(TAG, " Can not find address for symbol %s", sName); + return ELF_INVALID_ADDRESS; +} + +static bool read_symbol(FlipperApplication* e, int n, Elf32_Sym* sym, char* name, size_t nlen) { + bool success = false; + off_t old = storage_file_tell(e->fd); + off_t pos = e->symbol_table + n * sizeof(Elf32_Sym); + if(storage_file_seek(e->fd, pos, true) && + storage_file_read(e->fd, sym, sizeof(Elf32_Sym)) == sizeof(Elf32_Sym)) { + if(sym->st_name) + success = read_symbol_name(e, sym->st_name, name, nlen); + else { + Elf32_Shdr shdr; + success = read_section(e, sym->st_shndx, &shdr, name, nlen); + } + } + storage_file_seek(e->fd, old, true); + return success; +} + +static bool + relocation_cache_get(RelocationAddressCache_t cache, int symEntry, Elf32_Addr* symAddr) { + Elf32_Addr* addr = RelocationAddressCache_get(cache, symEntry); + if(addr) { + *symAddr = *addr; + return true; + } else { + return false; + } +} + +static void + relocation_cache_put(RelocationAddressCache_t cache, int symEntry, Elf32_Addr symAddr) { + RelocationAddressCache_set_at(cache, symEntry, symAddr); +} + +#define MAX_SYMBOL_NAME_LEN 128u + +static bool relocate(FlipperApplication* e, Elf32_Shdr* h, ELFSection_t* s) { + if(s->data) { + Elf32_Rel rel; + size_t relEntries = h->sh_size / sizeof(rel); + size_t relCount; + (void)storage_file_seek(e->fd, h->sh_offset, true); + FURI_LOG_D(TAG, " Offset Info Type Name"); + + int relocate_result = true; + char symbol_name[MAX_SYMBOL_NAME_LEN + 1] = {0}; + + for(relCount = 0; relCount < relEntries; relCount++) { + if(relCount % RESOLVER_THREAD_YIELD_STEP == 0) { + FURI_LOG_D(TAG, " reloc YIELD"); + furi_delay_tick(1); + } + + if(storage_file_read(e->fd, &rel, sizeof(Elf32_Rel)) != sizeof(Elf32_Rel)) { + FURI_LOG_E(TAG, " reloc read fail"); + return false; + } + + Elf32_Addr symAddr; + + int symEntry = ELF32_R_SYM(rel.r_info); + int relType = ELF32_R_TYPE(rel.r_info); + Elf32_Addr relAddr = ((Elf32_Addr)s->data) + rel.r_offset; + + if(!relocation_cache_get(e->relocation_cache, symEntry, &symAddr)) { + Elf32_Sym sym; + if(!read_symbol(e, symEntry, &sym, symbol_name, MAX_SYMBOL_NAME_LEN)) { + FURI_LOG_E(TAG, " symbol read fail"); + return false; + } + + FURI_LOG_D( + TAG, + " %08X %08X %-16s %s", + (unsigned int)rel.r_offset, + (unsigned int)rel.r_info, + type_to_str(relType), + symbol_name); + + symAddr = address_of(e, &sym, symbol_name); + relocation_cache_put(e->relocation_cache, symEntry, symAddr); + } + + if(symAddr != ELF_INVALID_ADDRESS) { + FURI_LOG_D( + TAG, + " symAddr=%08X relAddr=%08X", + (unsigned int)symAddr, + (unsigned int)relAddr); + if(!relocate_symbol(relAddr, relType, symAddr)) { + relocate_result = false; + } + } else { + FURI_LOG_D(TAG, " No symbol address of %s", symbol_name); + relocate_result = false; + } + } + + return relocate_result; + } else + FURI_LOG_I(TAG, "Section not loaded"); + + return false; +} + +static bool flipper_application_load_section_data(FlipperApplication* e, ELFSection_t* s) { + Elf32_Shdr section_header; + if(s->sec_idx == 0) { + FURI_LOG_I(TAG, "Section is not present"); + return true; + } + + if(!read_section_header(e, s->sec_idx, §ion_header)) { + return false; + } + + if(section_header.sh_size == 0) { + FURI_LOG_I(TAG, "No data for section"); + return true; + } + + s->data = aligned_malloc(section_header.sh_size, section_header.sh_addralign); + // e->state.mmap_entry_count++; + + if(section_header.sh_type == SHT_NOBITS) { + /* section is empty (.bss?) */ + /* no need to memset - allocator already did that */ + /* memset(s->data, 0, h->sh_size); */ + FURI_LOG_D(TAG, "0x%X", s->data); + return true; + } + + if((!storage_file_seek(e->fd, section_header.sh_offset, true)) || + (storage_file_read(e->fd, s->data, section_header.sh_size) != section_header.sh_size)) { + FURI_LOG_E(TAG, " seek/read fail"); + flipper_application_free_section(s); + return false; + } + + FURI_LOG_D(TAG, "0x%X", s->data); + return true; +} + +static bool flipper_application_relocate_section(FlipperApplication* e, ELFSection_t* s) { + Elf32_Shdr section_header; + if(s->rel_sec_idx) { + FURI_LOG_D(TAG, "Relocating section"); + if(read_section_header(e, s->rel_sec_idx, §ion_header)) + return relocate(e, §ion_header, s); + else { + FURI_LOG_E(TAG, "Error reading section header"); + return false; + } + } else + FURI_LOG_D(TAG, "No relocation index"); /* Not an error */ + return true; +} + +FlipperApplicationLoadStatus flipper_application_load_sections(FlipperApplication* e) { + FlipperApplicationLoadStatus status = FlipperApplicationLoadStatusSuccess; + RelocationAddressCache_init(e->relocation_cache); + size_t start = furi_get_tick(); + + struct { + ELFSection_t* section; + const char* name; + } sections[] = { + {&e->text, ".text"}, + {&e->rodata, ".rodata"}, + {&e->data, ".data"}, + {&e->bss, ".bss"}, + }; + + for(size_t i = 0; i < COUNT_OF(sections); i++) { + if(!flipper_application_load_section_data(e, sections[i].section)) { + FURI_LOG_E(TAG, "Error loading section '%s'", sections[i].name); + status = FlipperApplicationLoadStatusUnspecifiedError; + } + } + + if(status == FlipperApplicationLoadStatusSuccess) { + for(size_t i = 0; i < COUNT_OF(sections); i++) { + if(!flipper_application_relocate_section(e, sections[i].section)) { + FURI_LOG_E(TAG, "Error relocating section '%s'", sections[i].name); + status = FlipperApplicationLoadStatusMissingImports; + } + } + } + + if(status == FlipperApplicationLoadStatusSuccess) { + e->state.mmap_entries = + malloc(sizeof(FlipperApplicationMemoryMapEntry) * e->state.mmap_entry_count); + uint32_t mmap_entry_idx = 0; + for(size_t i = 0; i < COUNT_OF(sections); i++) { + const void* data_ptr = sections[i].section->data; + if(data_ptr) { + FURI_LOG_I(TAG, "0x%X %s", (uint32_t)data_ptr, sections[i].name); + e->state.mmap_entries[mmap_entry_idx].address = (uint32_t)data_ptr; + e->state.mmap_entries[mmap_entry_idx].name = sections[i].name; + mmap_entry_idx++; + } + } + furi_check(mmap_entry_idx == e->state.mmap_entry_count); + + /* Fixing up entry point */ + e->entry += (uint32_t)e->text.data; + } + + FURI_LOG_D(TAG, "Relocation cache size: %u", RelocationAddressCache_size(e->relocation_cache)); + RelocationAddressCache_clear(e->relocation_cache); + FURI_LOG_I(TAG, "Loaded in %ums", (size_t)(furi_get_tick() - start)); + + return status; +} + +void flipper_application_free_section(ELFSection_t* s) { + if(s->data) { + aligned_free(s->data); + } + s->data = NULL; +} diff --git a/lib/flipper_application/flipper_application.c b/lib/flipper_application/flipper_application.c new file mode 100644 index 00000000..6e84cce3 --- /dev/null +++ b/lib/flipper_application/flipper_application.c @@ -0,0 +1,131 @@ +#include "flipper_application.h" +#include "flipper_application_i.h" + +#define TAG "fapp" + +/* For debugger access to app state */ +FlipperApplication* last_loaded_app = NULL; + +FlipperApplication* + flipper_application_alloc(Storage* storage, const ElfApiInterface* api_interface) { + FlipperApplication* app = malloc(sizeof(FlipperApplication)); + app->api_interface = api_interface; + app->fd = storage_file_alloc(storage); + app->thread = NULL; + return app; +} + +void flipper_application_free(FlipperApplication* app) { + furi_assert(app); + + if(app->thread) { + furi_thread_join(app->thread); + furi_thread_free(app->thread); + } + + last_loaded_app = NULL; + + if(app->state.debug_link_size) { + free(app->state.debug_link); + } + + if(app->state.mmap_entries) { + free(app->state.mmap_entries); + } + + ELFSection_t* sections[] = {&app->text, &app->rodata, &app->data, &app->bss}; + for(size_t i = 0; i < COUNT_OF(sections); i++) { + flipper_application_free_section(sections[i]); + } + + storage_file_free(app->fd); + + free(app); +} + +/* Parse headers, load manifest */ +FlipperApplicationPreloadStatus + flipper_application_preload(FlipperApplication* app, const char* path) { + if(!flipper_application_load_elf_headers(app, path) || + !flipper_application_load_section_table(app)) { + return FlipperApplicationPreloadStatusInvalidFile; + } + + if((app->manifest.base.manifest_magic != FAP_MANIFEST_MAGIC) && + (app->manifest.base.manifest_version == FAP_MANIFEST_SUPPORTED_VERSION)) { + return FlipperApplicationPreloadStatusInvalidManifest; + } + + if(app->manifest.base.api_version.major != app->api_interface->api_version_major /* || + app->manifest.base.api_version.minor > app->api_interface->api_version_minor */) { + return FlipperApplicationPreloadStatusApiMismatch; + } + + return FlipperApplicationPreloadStatusSuccess; +} + +const FlipperApplicationManifest* flipper_application_get_manifest(FlipperApplication* app) { + return &app->manifest; +} + +FlipperApplicationLoadStatus flipper_application_map_to_memory(FlipperApplication* app) { + last_loaded_app = app; + return flipper_application_load_sections(app); +} + +const FlipperApplicationState* flipper_application_get_state(FlipperApplication* app) { + return &app->state; +} + +FuriThread* flipper_application_spawn(FlipperApplication* app, void* args) { + furi_check(app->thread == NULL); + + const FlipperApplicationManifest* manifest = flipper_application_get_manifest(app); + furi_check(manifest->stack_size > 0); + + app->thread = furi_thread_alloc(); + furi_thread_set_stack_size(app->thread, manifest->stack_size); + furi_thread_set_name(app->thread, manifest->name); + furi_thread_set_callback(app->thread, (entry_t*)app->entry); + furi_thread_set_context(app->thread, args); + + return app->thread; +} + +FuriThread* flipper_application_get_thread(FlipperApplication* app) { + return app->thread; +} + +void const* flipper_application_get_entry_address(FlipperApplication* app) { + return (void*)app->entry; +} + +static const char* preload_status_strings[] = { + [FlipperApplicationPreloadStatusSuccess] = "Success", + [FlipperApplicationPreloadStatusUnspecifiedError] = "Unknown error", + [FlipperApplicationPreloadStatusInvalidFile] = "Invalid file", + [FlipperApplicationPreloadStatusInvalidManifest] = "Invalid file manifest", + [FlipperApplicationPreloadStatusApiMismatch] = "API version mismatch", + [FlipperApplicationPreloadStatusTargetMismatch] = "Hardware target mismatch", +}; + +static const char* load_status_strings[] = { + [FlipperApplicationLoadStatusSuccess] = "Success", + [FlipperApplicationLoadStatusUnspecifiedError] = "Unknown error", + [FlipperApplicationLoadStatusNoFreeMemory] = "Out of memory", + [FlipperApplicationLoadStatusMissingImports] = "Found unsatisfied imports", +}; + +const char* flipper_application_preload_status_to_string(FlipperApplicationPreloadStatus status) { + if(status >= COUNT_OF(preload_status_strings) || preload_status_strings[status] == NULL) { + return "Unknown error"; + } + return preload_status_strings[status]; +} + +const char* flipper_application_load_status_to_string(FlipperApplicationLoadStatus status) { + if(status >= COUNT_OF(load_status_strings) || load_status_strings[status] == NULL) { + return "Unknown error"; + } + return load_status_strings[status]; +} diff --git a/lib/flipper_application/flipper_application.h b/lib/flipper_application/flipper_application.h new file mode 100644 index 00000000..34de4038 --- /dev/null +++ b/lib/flipper_application/flipper_application.h @@ -0,0 +1,129 @@ +#pragma once + +#include "application_manifest.h" +#include "elf/elf_api_interface.h" + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + FlipperApplicationPreloadStatusSuccess = 0, + FlipperApplicationPreloadStatusUnspecifiedError, + FlipperApplicationPreloadStatusInvalidFile, + FlipperApplicationPreloadStatusInvalidManifest, + FlipperApplicationPreloadStatusApiMismatch, + FlipperApplicationPreloadStatusTargetMismatch, +} FlipperApplicationPreloadStatus; + +typedef enum { + FlipperApplicationLoadStatusSuccess = 0, + FlipperApplicationLoadStatusUnspecifiedError, + FlipperApplicationLoadStatusNoFreeMemory, + FlipperApplicationLoadStatusMissingImports, +} FlipperApplicationLoadStatus; + +/** + * @brief Get text description of preload status + * @param status Status code + * @return String pointer to description + */ +const char* flipper_application_preload_status_to_string(FlipperApplicationPreloadStatus status); + +/** + * @brief Get text description of load status + * @param status Status code + * @return String pointer to description + */ +const char* flipper_application_load_status_to_string(FlipperApplicationLoadStatus status); + +typedef struct FlipperApplication FlipperApplication; + +typedef struct { + const char* name; + uint32_t address; +} FlipperApplicationMemoryMapEntry; + +typedef struct { + uint32_t mmap_entry_count; + FlipperApplicationMemoryMapEntry* mmap_entries; + uint32_t debug_link_size; + uint8_t* debug_link; +} FlipperApplicationState; + +/** + * @brief Initialize FlipperApplication object + * @param storage Storage instance + * @param api_interface ELF API interface to use for pre-loading and symbol resolving + * @return Application instance + */ +FlipperApplication* + flipper_application_alloc(Storage* storage, const ElfApiInterface* api_interface); + +/** + * @brief Destroy FlipperApplication object + * @param app Application pointer + */ +void flipper_application_free(FlipperApplication* app); + +/** + * @brief Validate elf file and load application metadata + * @param app Application pointer + * @return Preload result code + */ +FlipperApplicationPreloadStatus + flipper_application_preload(FlipperApplication* app, const char* path); + +/** + * @brief Get pointer to application manifest for preloaded application + * @param app Application pointer + * @return Pointer to application manifest + */ +const FlipperApplicationManifest* flipper_application_get_manifest(FlipperApplication* app); + +/** + * @brief Load sections and process relocations for already pre-loaded application + * @param app Application pointer + * @return Load result code + */ +FlipperApplicationLoadStatus flipper_application_map_to_memory(FlipperApplication* app); + +/** + * @brief Get state object for loaded application + * @param app Application pointer + * @return Pointer to state object + */ +const FlipperApplicationState* flipper_application_get_state(FlipperApplication* app); + +/** + * @brief Create application thread at entry point address, using app name and + * stack size from metadata. Returned thread isn't started yet. + * Can be only called once for application instance. + * @param app Applicaiton pointer + * @param args Object to pass to app's entry point + * @return Created thread + */ +FuriThread* flipper_application_spawn(FlipperApplication* app, void* args); + +/** + * @brief Get previously spawned thread + * @param app Application pointer + * @return Created thread + */ +FuriThread* flipper_application_get_thread(FlipperApplication* app); + +/** + * @brief Return relocated and valid address of app's entry point + * @param app Application pointer + * @return Address of app's entry point + */ +void const* flipper_application_get_entry_address(FlipperApplication* app); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/flipper_application/flipper_application_i.h b/lib/flipper_application/flipper_application_i.h new file mode 100644 index 00000000..8adf5c0d --- /dev/null +++ b/lib/flipper_application/flipper_application_i.h @@ -0,0 +1,99 @@ +#pragma once + +#include "elf.h" +#include "flipper_application.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +DICT_DEF2(RelocationAddressCache, int, M_DEFAULT_OPLIST, Elf32_Addr, M_DEFAULT_OPLIST) + +/** + * Callable elf entry type + */ +typedef int32_t(entry_t)(void*); + +typedef struct { + void* data; + uint16_t sec_idx; + uint16_t rel_sec_idx; +} ELFSection_t; + +struct FlipperApplication { + const ElfApiInterface* api_interface; + File* fd; + FlipperApplicationState state; + FlipperApplicationManifest manifest; + + size_t sections; + off_t section_table; + off_t section_table_strings; + + size_t symbol_count; + off_t symbol_table; + off_t symbol_table_strings; + off_t entry; + + ELFSection_t text; + ELFSection_t rodata; + ELFSection_t data; + ELFSection_t bss; + + FuriThread* thread; + RelocationAddressCache_t relocation_cache; +}; + +typedef enum { + FoundERROR = 0, + FoundSymTab = (1 << 0), + FoundStrTab = (1 << 2), + FoundText = (1 << 3), + FoundRodata = (1 << 4), + FoundData = (1 << 5), + FoundBss = (1 << 6), + FoundRelText = (1 << 7), + FoundRelRodata = (1 << 8), + FoundRelData = (1 << 9), + FoundRelBss = (1 << 10), + FoundFappManifest = (1 << 11), + FoundDebugLink = (1 << 12), + FoundValid = FoundSymTab | FoundStrTab | FoundFappManifest, + FoundExec = FoundValid | FoundText, + FoundGdbSection = FoundText | FoundRodata | FoundData | FoundBss, + FoundAll = FoundSymTab | FoundStrTab | FoundText | FoundRodata | FoundData | FoundBss | + FoundRelText | FoundRelRodata | FoundRelData | FoundRelBss | FoundDebugLink, +} FindFlags_t; + +/** + * @brief Load and validate basic ELF file headers + * @param e Application instance + * @param path FS path to application file + * @return true if ELF file is valid + */ +bool flipper_application_load_elf_headers(FlipperApplication* e, const char* path); + +/** + * @brief Iterate over all sections and save related indexes + * @param e Application instance + * @return true if all required sections are found + */ +bool flipper_application_load_section_table(FlipperApplication* e); + +/** + * @brief Load section data to memory and process relocations + * @param e Application instance + * @return Status code + */ +FlipperApplicationLoadStatus flipper_application_load_sections(FlipperApplication* e); + +/** + * @brief Release section data + * @param s section pointer + */ +void flipper_application_free_section(ELFSection_t* s); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/flipper_format/SConscript b/lib/flipper_format/SConscript index e5d61a07..5e185678 100644 --- a/lib/flipper_format/SConscript +++ b/lib/flipper_format/SConscript @@ -4,6 +4,10 @@ env.Append( CPPPATH=[ "#/lib/flipper_format", ], + SDK_HEADERS=[ + File("#/lib/flipper_format/flipper_format.h"), + File("#/lib/flipper_format/flipper_format_i.h"), + ], ) diff --git a/lib/lfrfid/SConscript b/lib/lfrfid/SConscript index 8d354288..fd29ca2e 100644 --- a/lib/lfrfid/SConscript +++ b/lib/lfrfid/SConscript @@ -7,6 +7,14 @@ env.Append( CPPPATH=[ "#/lib/lfrfid", ], + SDK_HEADERS=[ + File("#/lib/lfrfid/lfrfid_worker.h"), + File("#/lib/lfrfid/lfrfid_raw_worker.h"), + File("#/lib/lfrfid/lfrfid_raw_file.h"), + File("#/lib/lfrfid/lfrfid_dict_file.h"), + File("#/lib/lfrfid/tools/bit_lib.h"), + File("#/lib/lfrfid/protocols/lfrfid_protocols.h"), + ], ) libenv = env.Clone(FW_LIB_NAME="lfrfid") diff --git a/lib/lfrfid/protocols/protocol_awid.c b/lib/lfrfid/protocols/protocol_awid.c index 97c07d7b..7131d30d 100644 --- a/lib/lfrfid/protocols/protocol_awid.c +++ b/lib/lfrfid/protocols/protocol_awid.c @@ -205,6 +205,10 @@ bool protocol_awid_write_data(ProtocolAwid* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_awid_encode(protocol->data, (uint8_t*)protocol->encoded_data); + protocol_awid_decode(protocol->encoded_data, protocol->data); + protocol_awid_encode(protocol->data, (uint8_t*)protocol->encoded_data); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_em4100.c b/lib/lfrfid/protocols/protocol_em4100.c index 17f57421..6959f753 100644 --- a/lib/lfrfid/protocols/protocol_em4100.c +++ b/lib/lfrfid/protocols/protocol_em4100.c @@ -248,6 +248,14 @@ bool protocol_em4100_write_data(ProtocolEM4100* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_em4100_encoder_start(protocol); + em4100_decode( + (uint8_t*)&protocol->encoded_data, + sizeof(EM4100DecodedData), + protocol->data, + EM4100_DECODED_DATA_SIZE); + protocol_em4100_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_fdx_a.c b/lib/lfrfid/protocols/protocol_fdx_a.c index 23f9e285..554b9071 100644 --- a/lib/lfrfid/protocols/protocol_fdx_a.c +++ b/lib/lfrfid/protocols/protocol_fdx_a.c @@ -178,6 +178,10 @@ bool protocol_fdx_a_write_data(ProtocolFDXA* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_fdx_a_encoder_start(protocol); + protocol_fdx_a_decode(protocol->encoded_data, protocol->data); + protocol_fdx_a_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_fdx_b.c b/lib/lfrfid/protocols/protocol_fdx_b.c index f68a884e..f42b4ed9 100644 --- a/lib/lfrfid/protocols/protocol_fdx_b.c +++ b/lib/lfrfid/protocols/protocol_fdx_b.c @@ -334,6 +334,10 @@ bool protocol_fdx_b_write_data(ProtocolFDXB* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_fdx_b_encoder_start(protocol); + protocol_fdx_b_decode(protocol); + protocol_fdx_b_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_gallagher.c b/lib/lfrfid/protocols/protocol_gallagher.c index c205ab8a..5d824530 100644 --- a/lib/lfrfid/protocols/protocol_gallagher.c +++ b/lib/lfrfid/protocols/protocol_gallagher.c @@ -249,6 +249,10 @@ bool protocol_gallagher_write_data(ProtocolGallagher* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_gallagher_encoder_start(protocol); + protocol_gallagher_decode(protocol); + protocol_gallagher_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_h10301.c b/lib/lfrfid/protocols/protocol_h10301.c index f30f75fa..6c50c667 100644 --- a/lib/lfrfid/protocols/protocol_h10301.c +++ b/lib/lfrfid/protocols/protocol_h10301.c @@ -337,6 +337,10 @@ bool protocol_h10301_write_data(ProtocolH10301* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_h10301_encoder_start(protocol); + protocol_h10301_decode(protocol->encoded_data, protocol->data); + protocol_h10301_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_hid_ex_generic.c b/lib/lfrfid/protocols/protocol_hid_ex_generic.c index e0a85266..17b75528 100644 --- a/lib/lfrfid/protocols/protocol_hid_ex_generic.c +++ b/lib/lfrfid/protocols/protocol_hid_ex_generic.c @@ -171,6 +171,10 @@ bool protocol_hid_ex_generic_write_data(ProtocolHIDEx* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_hid_ex_generic_encoder_start(protocol); + protocol_hid_ex_generic_decode(protocol->encoded_data, protocol->data); + protocol_hid_ex_generic_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_hid_generic.c b/lib/lfrfid/protocols/protocol_hid_generic.c index 2516d681..da5f5b7c 100644 --- a/lib/lfrfid/protocols/protocol_hid_generic.c +++ b/lib/lfrfid/protocols/protocol_hid_generic.c @@ -203,6 +203,10 @@ bool protocol_hid_generic_write_data(ProtocolHID* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_hid_generic_encoder_start(protocol); + protocol_hid_generic_decode(protocol->encoded_data, protocol->data); + protocol_hid_generic_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_io_prox_xsf.c b/lib/lfrfid/protocols/protocol_io_prox_xsf.c index 66b1610b..f53eac68 100644 --- a/lib/lfrfid/protocols/protocol_io_prox_xsf.c +++ b/lib/lfrfid/protocols/protocol_io_prox_xsf.c @@ -259,6 +259,10 @@ bool protocol_io_prox_xsf_write_data(ProtocolIOProxXSF* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_io_prox_xsf_encode(protocol->data, protocol->encoded_data); + protocol_io_prox_xsf_decode(protocol->encoded_data, protocol->data); + protocol_io_prox_xsf_encode(protocol->data, protocol->encoded_data); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_jablotron.c b/lib/lfrfid/protocols/protocol_jablotron.c index e00b1e59..89a59a2d 100644 --- a/lib/lfrfid/protocols/protocol_jablotron.c +++ b/lib/lfrfid/protocols/protocol_jablotron.c @@ -169,6 +169,10 @@ bool protocol_jablotron_write_data(ProtocolJablotron* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_jablotron_encoder_start(protocol); + protocol_jablotron_decode(protocol); + protocol_jablotron_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_pac_stanley.c b/lib/lfrfid/protocols/protocol_pac_stanley.c index 7ab16a10..b5e1ebdd 100644 --- a/lib/lfrfid/protocols/protocol_pac_stanley.c +++ b/lib/lfrfid/protocols/protocol_pac_stanley.c @@ -182,6 +182,10 @@ bool protocol_pac_stanley_write_data(ProtocolPACStanley* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_pac_stanley_encoder_start(protocol); + protocol_pac_stanley_decode(protocol); + protocol_pac_stanley_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_paradox.c b/lib/lfrfid/protocols/protocol_paradox.c index be627600..b0b3e71d 100644 --- a/lib/lfrfid/protocols/protocol_paradox.c +++ b/lib/lfrfid/protocols/protocol_paradox.c @@ -162,6 +162,10 @@ bool protocol_paradox_write_data(ProtocolParadox* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_paradox_encode(protocol->data, (uint8_t*)protocol->encoded_data); + protocol_paradox_decode(protocol->encoded_data, protocol->data); + protocol_paradox_encode(protocol->data, (uint8_t*)protocol->encoded_data); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_pyramid.c b/lib/lfrfid/protocols/protocol_pyramid.c index a0404b48..1bba9871 100644 --- a/lib/lfrfid/protocols/protocol_pyramid.c +++ b/lib/lfrfid/protocols/protocol_pyramid.c @@ -219,6 +219,10 @@ bool protocol_pyramid_write_data(ProtocolPyramid* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_pyramid_encode(protocol); + protocol_pyramid_decode(protocol); + protocol_pyramid_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_viking.c b/lib/lfrfid/protocols/protocol_viking.c index 6119b734..f252cc2c 100644 --- a/lib/lfrfid/protocols/protocol_viking.c +++ b/lib/lfrfid/protocols/protocol_viking.c @@ -157,6 +157,10 @@ bool protocol_viking_write_data(ProtocolViking* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_viking_encoder_start(protocol); + protocol_viking_decode(protocol); + protocol_viking_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfs_config.h b/lib/lfs_config.h index 59b3c486..ff8bc4b2 100644 --- a/lib/lfs_config.h +++ b/lib/lfs_config.h @@ -5,21 +5,26 @@ #ifdef FURI_NDEBUG #define LFS_NO_ASSERT #define LFS_ASSERT(x) -#else +#else #define LFS_ASSERT furi_assert #endif #define LFS_TAG "Lfs" +#ifdef FURI_LFS_DEBUG #define LFS_TRACE(...) FURI_LOG_T(LFS_TAG, __VA_ARGS__); #define LFS_DEBUG(...) FURI_LOG_D(LFS_TAG, __VA_ARGS__); +#else +#define LFS_TRACE(...) + +#define LFS_DEBUG(...) +#endif // FURI_LFS_DEBUG #define LFS_WARN(...) FURI_LOG_W(LFS_TAG, __VA_ARGS__); #define LFS_ERROR(...) FURI_LOG_E(LFS_TAG, __VA_ARGS__); - // Because crc #undef LFS_CONFIG @@ -35,16 +40,13 @@ #ifndef LFS_NO_ASSERT #include #endif -#if !defined(LFS_NO_DEBUG) || \ - !defined(LFS_NO_WARN) || \ - !defined(LFS_NO_ERROR) || \ - defined(LFS_YES_TRACE) +#if !defined(LFS_NO_DEBUG) || !defined(LFS_NO_WARN) || !defined(LFS_NO_ERROR) || \ + defined(LFS_YES_TRACE) #include #endif #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif // Builtin functions, these may be replaced by more efficient @@ -66,21 +68,29 @@ static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) { } static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) { - return lfs_aligndown(a + alignment-1, alignment); + return lfs_aligndown(a + alignment - 1, alignment); } // Find the smallest power of 2 greater than or equal to a static inline uint32_t lfs_npw2(uint32_t a) { #if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) - return 32 - __builtin_clz(a-1); + return 32 - __builtin_clz(a - 1); #else uint32_t r = 0; uint32_t s; a -= 1; - s = (a > 0xffff) << 4; a >>= s; r |= s; - s = (a > 0xff ) << 3; a >>= s; r |= s; - s = (a > 0xf ) << 2; a >>= s; r |= s; - s = (a > 0x3 ) << 1; a >>= s; r |= s; + s = (a > 0xffff) << 4; + a >>= s; + r |= s; + s = (a > 0xff) << 3; + a >>= s; + r |= s; + s = (a > 0xf) << 2; + a >>= s; + r |= s; + s = (a > 0x3) << 1; + a >>= s; + r |= s; return (r | (a >> 1)) + 1; #endif } @@ -114,20 +124,23 @@ static inline int lfs_scmp(uint32_t a, uint32_t b) { // Convert between 32-bit little-endian and native order static inline uint32_t lfs_fromle32(uint32_t a) { -#if !defined(LFS_NO_INTRINSICS) && ( \ - (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ - (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ - (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) +#if !defined(LFS_NO_INTRINSICS) && \ + ((defined(BYTE_ORDER) && defined(ORDER_LITTLE_ENDIAN) && \ + BYTE_ORDER == ORDER_LITTLE_ENDIAN) || \ + (defined(__BYTE_ORDER) && defined(__ORDER_LITTLE_ENDIAN) && \ + __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) return a; -#elif !defined(LFS_NO_INTRINSICS) && ( \ - (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ - (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ - (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) +#elif !defined(LFS_NO_INTRINSICS) && \ + ((defined(BYTE_ORDER) && defined(ORDER_BIG_ENDIAN) && BYTE_ORDER == ORDER_BIG_ENDIAN) || \ + (defined(__BYTE_ORDER) && defined(__ORDER_BIG_ENDIAN) && \ + __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) return __builtin_bswap32(a); #else - return (((uint8_t*)&a)[0] << 0) | - (((uint8_t*)&a)[1] << 8) | - (((uint8_t*)&a)[2] << 16) | + return (((uint8_t*)&a)[0] << 0) | (((uint8_t*)&a)[1] << 8) | (((uint8_t*)&a)[2] << 16) | (((uint8_t*)&a)[3] << 24); #endif } @@ -138,21 +151,24 @@ static inline uint32_t lfs_tole32(uint32_t a) { // Convert between 32-bit big-endian and native order static inline uint32_t lfs_frombe32(uint32_t a) { -#if !defined(LFS_NO_INTRINSICS) && ( \ - (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ - (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ - (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) +#if !defined(LFS_NO_INTRINSICS) && \ + ((defined(BYTE_ORDER) && defined(ORDER_LITTLE_ENDIAN) && \ + BYTE_ORDER == ORDER_LITTLE_ENDIAN) || \ + (defined(__BYTE_ORDER) && defined(__ORDER_LITTLE_ENDIAN) && \ + __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) return __builtin_bswap32(a); -#elif !defined(LFS_NO_INTRINSICS) && ( \ - (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ - (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ - (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) +#elif !defined(LFS_NO_INTRINSICS) && \ + ((defined(BYTE_ORDER) && defined(ORDER_BIG_ENDIAN) && BYTE_ORDER == ORDER_BIG_ENDIAN) || \ + (defined(__BYTE_ORDER) && defined(__ORDER_BIG_ENDIAN) && \ + __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) return a; #else - return (((uint8_t*)&a)[0] << 24) | - (((uint8_t*)&a)[1] << 16) | - (((uint8_t*)&a)[2] << 8) | - (((uint8_t*)&a)[3] << 0); + return (((uint8_t*)&a)[0] << 24) | (((uint8_t*)&a)[1] << 16) | (((uint8_t*)&a)[2] << 8) | + (((uint8_t*)&a)[3] << 0); #endif } @@ -161,11 +177,11 @@ static inline uint32_t lfs_tobe32(uint32_t a) { } // Calculate CRC-32 with polynomial = 0x04c11db7 -uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size); +uint32_t lfs_crc(uint32_t crc, const void* buffer, size_t size); // Allocate memory, only used if buffers are not provided to littlefs // Note, memory must be 64-bit aligned -static inline void *lfs_malloc(size_t size) { +static inline void* lfs_malloc(size_t size) { #ifndef LFS_NO_MALLOC return malloc(size); #else @@ -175,7 +191,7 @@ static inline void *lfs_malloc(size_t size) { } // Deallocate memory, only used if buffers are not provided to littlefs -static inline void lfs_free(void *p) { +static inline void lfs_free(void* p) { #ifndef LFS_NO_MALLOC free(p); #else @@ -183,7 +199,6 @@ static inline void lfs_free(void *p) { #endif } - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/lib/littlefs b/lib/littlefs index 1863dc78..40dba4a5 160000 --- a/lib/littlefs +++ b/lib/littlefs @@ -1 +1 @@ -Subproject commit 1863dc7883d82bd6ca79faa164b65341064d1c16 +Subproject commit 40dba4a556e0d81dfbe64301a6aa4e18ceca896c diff --git a/lib/loclass.scons b/lib/loclass.scons deleted file mode 100644 index a657f042..00000000 --- a/lib/loclass.scons +++ /dev/null @@ -1,17 +0,0 @@ -Import("env") - -env.Append( - CPPPATH=[ - "#/lib/loclass", - ], -) - - -libenv = env.Clone(FW_LIB_NAME="loclass") -libenv.ApplyLibFlags() - -sources = Glob("loclass/*.c", source=True) - -lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) -libenv.Install("${LIB_DIST_DIR}", lib) -Return("lib") diff --git a/lib/mbedtls.scons b/lib/mbedtls.scons index e39d9dae..b57221a4 100644 --- a/lib/mbedtls.scons +++ b/lib/mbedtls.scons @@ -11,6 +11,14 @@ env.Append( libenv = env.Clone(FW_LIB_NAME="mbedtls") libenv.ApplyLibFlags() +libenv.AppendUnique( + CCFLAGS=[ + # Required for lib to be linkable with .faps + "-mword-relocations", + "-mlong-calls", + ], +) + sources = [ "mbedtls/library/des.c", "mbedtls/library/sha1.c", diff --git a/lib/misc.scons b/lib/misc.scons index 5a826b18..b7d8554b 100644 --- a/lib/misc.scons +++ b/lib/misc.scons @@ -12,6 +12,9 @@ env.Append( CPPDEFINES=[ "PB_ENABLE_MALLOC", ], + SDK_HEADERS=[ + File("#/lib/micro-ecc/uECC.h"), + ], ) diff --git a/lib/nfc/helpers/mf_classic_dict.c b/lib/nfc/helpers/mf_classic_dict.c index 410ddbd8..5bb67145 100644 --- a/lib/nfc/helpers/mf_classic_dict.c +++ b/lib/nfc/helpers/mf_classic_dict.c @@ -5,6 +5,7 @@ #define MF_CLASSIC_DICT_FLIPPER_PATH EXT_PATH("nfc/assets/mf_classic_dict.nfc") #define MF_CLASSIC_DICT_USER_PATH EXT_PATH("nfc/assets/mf_classic_dict_user.nfc") +#define MF_CLASSIC_DICT_UNIT_TEST_PATH EXT_PATH("unit_tests/mf_classic_dict.nfc") #define TAG "MfClassicDict" @@ -23,6 +24,9 @@ bool mf_classic_dict_check_presence(MfClassicDictType dict_type) { dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_FLIPPER_PATH, NULL) == FSE_OK; } else if(dict_type == MfClassicDictTypeUser) { dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_USER_PATH, NULL) == FSE_OK; + } else if(dict_type == MfClassicDictTypeUnitTest) { + dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_UNIT_TEST_PATH, NULL) == + FSE_OK; } furi_record_close(RECORD_STORAGE); @@ -50,6 +54,15 @@ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) { buffered_file_stream_close(dict->stream); break; } + } else if(dict_type == MfClassicDictTypeUnitTest) { + if(!buffered_file_stream_open( + dict->stream, + MF_CLASSIC_DICT_UNIT_TEST_PATH, + FSAM_READ_WRITE, + FSOM_CREATE_ALWAYS)) { + buffered_file_stream_close(dict->stream); + break; + } } // Read total amount of keys @@ -86,38 +99,30 @@ void mf_classic_dict_free(MfClassicDict* dict) { free(dict); } +static void mf_classic_dict_int_to_str(uint8_t* key_int, string_t key_str) { + string_reset(key_str); + for(size_t i = 0; i < 6; i++) { + string_cat_printf(key_str, "%02X", key_int[i]); + } +} + +static void mf_classic_dict_str_to_int(string_t key_str, uint64_t* key_int) { + uint8_t key_byte_tmp; + + *key_int = 0ULL; + for(uint8_t i = 0; i < 12; i += 2) { + args_char_to_hex( + string_get_char(key_str, i), string_get_char(key_str, i + 1), &key_byte_tmp); + *key_int |= (uint64_t)key_byte_tmp << 8 * (5 - i / 2); + } +} + uint32_t mf_classic_dict_get_total_keys(MfClassicDict* dict) { furi_assert(dict); return dict->total_keys; } -bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key) { - furi_assert(dict); - furi_assert(dict->stream); - - uint8_t key_byte_tmp = 0; - string_t next_line; - string_init(next_line); - - bool key_read = false; - *key = 0ULL; - while(!key_read) { - if(!stream_read_line(dict->stream, next_line)) break; - if(string_get_char(next_line, 0) == '#') continue; - if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; - for(uint8_t i = 0; i < 12; i += 2) { - args_char_to_hex( - string_get_char(next_line, i), string_get_char(next_line, i + 1), &key_byte_tmp); - *key |= (uint64_t)key_byte_tmp << 8 * (5 - i / 2); - } - key_read = true; - } - - string_clear(next_line); - return key_read; -} - bool mf_classic_dict_rewind(MfClassicDict* dict) { furi_assert(dict); furi_assert(dict->stream); @@ -125,24 +130,194 @@ bool mf_classic_dict_rewind(MfClassicDict* dict) { return stream_rewind(dict->stream); } -bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key) { +bool mf_classic_dict_get_next_key_str(MfClassicDict* dict, string_t key) { furi_assert(dict); furi_assert(dict->stream); - string_t key_str; - string_init(key_str); - for(size_t i = 0; i < 6; i++) { - string_cat_printf(key_str, "%02X", key[i]); + bool key_read = false; + string_reset(key); + while(!key_read) { + if(!stream_read_line(dict->stream, key)) break; + if(string_get_char(key, 0) == '#') continue; + if(string_size(key) != NFC_MF_CLASSIC_KEY_LEN) continue; + string_left(key, 12); + key_read = true; } - string_cat_printf(key_str, "\n"); + + return key_read; +} + +bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key) { + furi_assert(dict); + furi_assert(dict->stream); + + string_t temp_key; + string_init(temp_key); + bool key_read = mf_classic_dict_get_next_key_str(dict, temp_key); + if(key_read) { + mf_classic_dict_str_to_int(temp_key, key); + } + string_clear(temp_key); + return key_read; +} + +bool mf_classic_dict_is_key_present_str(MfClassicDict* dict, string_t key) { + furi_assert(dict); + furi_assert(dict->stream); + + string_t next_line; + string_init(next_line); + + bool key_found = false; + stream_rewind(dict->stream); + while(!key_found) { + if(!stream_read_line(dict->stream, next_line)) break; + if(string_get_char(next_line, 0) == '#') continue; + if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; + string_left(next_line, 12); + if(!string_equal_p(key, next_line)) continue; + key_found = true; + } + + string_clear(next_line); + return key_found; +} + +bool mf_classic_dict_is_key_present(MfClassicDict* dict, uint8_t* key) { + string_t temp_key; + + string_init(temp_key); + mf_classic_dict_int_to_str(key, temp_key); + bool key_found = mf_classic_dict_is_key_present_str(dict, temp_key); + string_clear(temp_key); + return key_found; +} + +bool mf_classic_dict_add_key_str(MfClassicDict* dict, string_t key) { + furi_assert(dict); + furi_assert(dict->stream); + + string_cat_printf(key, "\n"); bool key_added = false; do { if(!stream_seek(dict->stream, 0, StreamOffsetFromEnd)) break; - if(!stream_insert_string(dict->stream, key_str)) break; + if(!stream_insert_string(dict->stream, key)) break; + dict->total_keys++; key_added = true; } while(false); - string_clear(key_str); + string_left(key, 12); return key_added; } + +bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key) { + furi_assert(dict); + furi_assert(dict->stream); + + string_t temp_key; + string_init(temp_key); + mf_classic_dict_int_to_str(key, temp_key); + bool key_added = mf_classic_dict_add_key_str(dict, temp_key); + + string_clear(temp_key); + return key_added; +} + +bool mf_classic_dict_get_key_at_index_str(MfClassicDict* dict, string_t key, uint32_t target) { + furi_assert(dict); + furi_assert(dict->stream); + + string_t next_line; + uint32_t index = 0; + string_init(next_line); + string_reset(key); + + bool key_found = false; + while(!key_found) { + if(!stream_read_line(dict->stream, next_line)) break; + if(string_get_char(next_line, 0) == '#') continue; + if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; + if(index++ != target) continue; + string_set_n(key, next_line, 0, 12); + key_found = true; + } + + string_clear(next_line); + return key_found; +} + +bool mf_classic_dict_get_key_at_index(MfClassicDict* dict, uint64_t* key, uint32_t target) { + furi_assert(dict); + furi_assert(dict->stream); + + string_t temp_key; + string_init(temp_key); + bool key_found = mf_classic_dict_get_key_at_index_str(dict, temp_key, target); + if(key_found) { + mf_classic_dict_str_to_int(temp_key, key); + } + string_clear(temp_key); + return key_found; +} + +bool mf_classic_dict_find_index_str(MfClassicDict* dict, string_t key, uint32_t* target) { + furi_assert(dict); + furi_assert(dict->stream); + + string_t next_line; + string_init(next_line); + + bool key_found = false; + uint32_t index = 0; + stream_rewind(dict->stream); + while(!key_found) { + if(!stream_read_line(dict->stream, next_line)) break; + if(string_get_char(next_line, 0) == '#') continue; + if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; + string_left(next_line, 12); + if(!string_equal_p(key, next_line)) continue; + key_found = true; + *target = index; + } + + string_clear(next_line); + return key_found; +} + +bool mf_classic_dict_find_index(MfClassicDict* dict, uint8_t* key, uint32_t* target) { + furi_assert(dict); + furi_assert(dict->stream); + + string_t temp_key; + string_init(temp_key); + mf_classic_dict_int_to_str(key, temp_key); + bool key_found = mf_classic_dict_find_index_str(dict, temp_key, target); + + string_clear(temp_key); + return key_found; +} + +bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target) { + furi_assert(dict); + furi_assert(dict->stream); + + string_t next_line; + string_init(next_line); + uint32_t index = 0; + + bool key_removed = false; + while(!key_removed) { + if(!stream_read_line(dict->stream, next_line)) break; + if(string_get_char(next_line, 0) == '#') continue; + if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; + if(index++ != target) continue; + stream_seek(dict->stream, -NFC_MF_CLASSIC_KEY_LEN, StreamOffsetFromCurrent); + if(!stream_delete(dict->stream, NFC_MF_CLASSIC_KEY_LEN)) break; + dict->total_keys--; + key_removed = true; + } + + string_clear(next_line); + return key_removed; +} diff --git a/lib/nfc/helpers/mf_classic_dict.h b/lib/nfc/helpers/mf_classic_dict.h index 2654e668..9241a37b 100644 --- a/lib/nfc/helpers/mf_classic_dict.h +++ b/lib/nfc/helpers/mf_classic_dict.h @@ -9,20 +9,91 @@ typedef enum { MfClassicDictTypeUser, MfClassicDictTypeFlipper, + MfClassicDictTypeUnitTest, } MfClassicDictType; typedef struct MfClassicDict MfClassicDict; bool mf_classic_dict_check_presence(MfClassicDictType dict_type); +/** Allocate MfClassicDict instance + * + * @param[in] dict_type The dictionary type + * + * @return MfClassicDict instance + */ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type); +/** Free MfClassicDict instance + * + * @param dict MfClassicDict instance + */ void mf_classic_dict_free(MfClassicDict* dict); +/** Get total keys count + * + * @param dict MfClassicDict instance + * + * @return total keys count + */ uint32_t mf_classic_dict_get_total_keys(MfClassicDict* dict); +/** Rewind to the beginning + * + * @param dict MfClassicDict instance + * + * @return true on success + */ +bool mf_classic_dict_rewind(MfClassicDict* dict); + +bool mf_classic_dict_is_key_present(MfClassicDict* dict, uint8_t* key); + +bool mf_classic_dict_is_key_present_str(MfClassicDict* dict, string_t key); + bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key); -bool mf_classic_dict_rewind(MfClassicDict* dict); +bool mf_classic_dict_get_next_key_str(MfClassicDict* dict, string_t key); + +/** Get key at target offset as uint64_t + * + * @param dict MfClassicDict instance + * @param[out] key Pointer to the uint64_t key + * @param[in] target Target offset from current position + * + * @return true on success + */ +bool mf_classic_dict_get_key_at_index(MfClassicDict* dict, uint64_t* key, uint32_t target); + +/** Get key at target offset as string_t + * + * @param dict MfClassicDict instance + * @param[out] key Found key destination buffer + * @param[in] target Target offset from current position + * + * @return true on success + */ +bool mf_classic_dict_get_key_at_index_str(MfClassicDict* dict, string_t key, uint32_t target); bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key); + +/** Add string representation of the key + * + * @param dict MfClassicDict instance + * @param[in] key String representation of the key + * + * @return true on success + */ +bool mf_classic_dict_add_key_str(MfClassicDict* dict, string_t key); + +bool mf_classic_dict_find_index(MfClassicDict* dict, uint8_t* key, uint32_t* target); + +bool mf_classic_dict_find_index_str(MfClassicDict* dict, string_t key, uint32_t* target); + +/** Delete key at target offset + * + * @param dict MfClassicDict instance + * @param[in] target Target offset from current position + * + * @return true on success + */ +bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target); diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index ea06ae70..dd78e2da 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -1182,8 +1182,19 @@ bool nfc_file_select(NfcDevice* dev) { // Input events and views are managed by file_browser string_t nfc_app_folder; string_init_set_str(nfc_app_folder, NFC_APP_FOLDER); - bool res = dialog_file_browser_show( - dev->dialogs, dev->load_path, nfc_app_folder, NFC_APP_EXTENSION, true, &I_Nfc_10px, true); + + const DialogsFileBrowserOptions browser_options = { + .extension = NFC_APP_EXTENSION, + .skip_assets = true, + .icon = &I_Nfc_10px, + .hide_ext = true, + .item_loader_callback = NULL, + .item_loader_context = NULL, + }; + + bool res = + dialog_file_browser_show(dev->dialogs, dev->load_path, nfc_app_folder, &browser_options); + string_clear(nfc_app_folder); if(res) { string_t filename; diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 6355f8d1..2feae443 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -123,7 +123,25 @@ static bool nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker, FuriHalNfcTxRxC } do { - // Read card + // Try to read supported card + FURI_LOG_I(TAG, "Trying to read a supported card ..."); + for(size_t i = 0; i < NfcSupportedCardTypeEnd; i++) { + if(nfc_supported_card[i].protocol == NfcDeviceProtocolMifareUl) { + if(nfc_supported_card[i].verify(nfc_worker, tx_rx)) { + if(nfc_supported_card[i].read(nfc_worker, tx_rx)) { + read_success = true; + nfc_supported_card[i].parse(nfc_worker->dev_data); + break; + } + } else { + furi_hal_nfc_sleep(); + } + } + } + if(read_success) break; + furi_hal_nfc_sleep(); + + // Otherwise, try to read as usual if(!furi_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 200)) break; if(!mf_ul_read_card(tx_rx, &reader, &data)) break; // Copy data @@ -149,14 +167,17 @@ static bool nfc_worker_read_mf_classic(NfcWorker* nfc_worker, FuriHalNfcTxRxCont do { // Try to read supported card - FURI_LOG_I(TAG, "Try read supported card ..."); + FURI_LOG_I(TAG, "Trying to read a supported card ..."); for(size_t i = 0; i < NfcSupportedCardTypeEnd; i++) { if(nfc_supported_card[i].protocol == NfcDeviceProtocolMifareClassic) { if(nfc_supported_card[i].verify(nfc_worker, tx_rx)) { if(nfc_supported_card[i].read(nfc_worker, tx_rx)) { read_success = true; nfc_supported_card[i].parse(nfc_worker->dev_data); + break; } + } else { + furi_hal_nfc_sleep(); } } } diff --git a/lib/nfc/parsers/all_in_one.c b/lib/nfc/parsers/all_in_one.c new file mode 100644 index 00000000..b49a32f7 --- /dev/null +++ b/lib/nfc/parsers/all_in_one.c @@ -0,0 +1,113 @@ +#include "nfc_supported_card.h" +#include "all_in_one.h" + +#include +#include + +#include "furi_hal.h" + +#define ALL_IN_ONE_LAYOUT_UNKNOWN 0 +#define ALL_IN_ONE_LAYOUT_A 1 +#define ALL_IN_ONE_LAYOUT_D 2 +#define ALL_IN_ONE_LAYOUT_E2 3 +#define ALL_IN_ONE_LAYOUT_E3 4 +#define ALL_IN_ONE_LAYOUT_E5 5 +#define ALL_IN_ONE_LAYOUT_2 6 + +uint8_t all_in_one_get_layout(NfcDeviceData* dev_data) { + // I absolutely hate what's about to happen here. + + // Switch on the second half of the third byte of page 5 + FURI_LOG_I("all_in_one", "Layout byte: %02x", dev_data->mf_ul_data.data[(4 * 5) + 2]); + FURI_LOG_I( + "all_in_one", "Layout half-byte: %02x", dev_data->mf_ul_data.data[(4 * 5) + 3] & 0x0F); + switch(dev_data->mf_ul_data.data[(4 * 5) + 2] & 0x0F) { + // If it is A, the layout type is a type A layout + case 0x0A: + return ALL_IN_ONE_LAYOUT_A; + case 0x0D: + return ALL_IN_ONE_LAYOUT_D; + case 0x02: + return ALL_IN_ONE_LAYOUT_2; + default: + FURI_LOG_I( + "all_in_one", + "Unknown layout type: %d", + dev_data->mf_ul_data.data[(4 * 5) + 2] & 0x0F); + return ALL_IN_ONE_LAYOUT_UNKNOWN; + } +} + +bool all_in_one_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { + UNUSED(nfc_worker); + // If this is a all_in_one pass, first 2 bytes of page 4 are 0x45 0xD9 + MfUltralightReader reader = {}; + MfUltralightData data = {}; + + if(!mf_ul_read_card(tx_rx, &reader, &data)) { + return false; + } else { + if(data.data[4 * 4] == 0x45 && data.data[4 * 4 + 1] == 0xD9) { + FURI_LOG_I("all_in_one", "Pass verified"); + return true; + } + } + return false; +} + +bool all_in_one_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { + MfUltralightReader reader = {}; + MfUltralightData data = {}; + if(!mf_ul_read_card(tx_rx, &reader, &data)) { + return false; + } else { + memcpy(&nfc_worker->dev_data->mf_ul_data, &data, sizeof(data)); + FURI_LOG_I("all_in_one", "Card read"); + return true; + } +} + +bool all_in_one_parser_parse(NfcDeviceData* dev_data) { + if(dev_data->mf_ul_data.data[4 * 4] != 0x45 || dev_data->mf_ul_data.data[4 * 4 + 1] != 0xD9) { + FURI_LOG_I("all_in_one", "Pass not verified"); + return false; + } + + // If the layout is a then the ride count is stored in the first byte of page 8 + uint8_t ride_count = 0; + uint32_t serial = 0; + if(all_in_one_get_layout(dev_data) == ALL_IN_ONE_LAYOUT_A) { + ride_count = dev_data->mf_ul_data.data[4 * 8]; + } else if(all_in_one_get_layout(dev_data) == ALL_IN_ONE_LAYOUT_D) { + // If the layout is D, the ride count is stored in the second byte of page 9 + ride_count = dev_data->mf_ul_data.data[4 * 9 + 1]; + // I hate this with a burning passion. + + // The number starts at the second half of the third byte on page 4, and is 32 bits long + // So we get the second half of the third byte, then bytes 4-6, and then the first half of the 7th byte + // B8 17 A2 A4 BD becomes 81 7A 2A 4B + serial = (dev_data->mf_ul_data.data[4 * 4 + 2] & 0x0F) << 28 | + dev_data->mf_ul_data.data[4 * 4 + 3] << 20 | + dev_data->mf_ul_data.data[4 * 4 + 4] << 12 | + dev_data->mf_ul_data.data[4 * 4 + 5] << 4 | + (dev_data->mf_ul_data.data[4 * 4 + 6] >> 4); + } else { + FURI_LOG_I("all_in_one", "Unknown layout: %d", all_in_one_get_layout(dev_data)); + ride_count = 137; + } + + // I hate this with a burning passion. + + // The number starts at the second half of the third byte on page 4, and is 32 bits long + // So we get the second half of the third byte, then bytes 4-6, and then the first half of the 7th byte + // B8 17 A2 A4 BD becomes 81 7A 2A 4B + serial = + (dev_data->mf_ul_data.data[4 * 4 + 2] & 0x0F) << 28 | + dev_data->mf_ul_data.data[4 * 4 + 3] << 20 | dev_data->mf_ul_data.data[4 * 4 + 4] << 12 | + dev_data->mf_ul_data.data[4 * 4 + 5] << 4 | (dev_data->mf_ul_data.data[4 * 4 + 6] >> 4); + + // Format string for rides count + string_printf( + dev_data->parsed_data, "\e#All-In-One\nNumber: %u\nRides left: %u", serial, ride_count); + return true; +} \ No newline at end of file diff --git a/lib/nfc/parsers/all_in_one.h b/lib/nfc/parsers/all_in_one.h new file mode 100644 index 00000000..9b646d4d --- /dev/null +++ b/lib/nfc/parsers/all_in_one.h @@ -0,0 +1,9 @@ +#pragma once + +#include "nfc_supported_card.h" + +bool all_in_one_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); + +bool all_in_one_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); + +bool all_in_one_parser_parse(NfcDeviceData* dev_data); \ No newline at end of file diff --git a/lib/nfc/parsers/nfc_supported_card.c b/lib/nfc/parsers/nfc_supported_card.c index 480c970e..fc2dc34e 100644 --- a/lib/nfc/parsers/nfc_supported_card.c +++ b/lib/nfc/parsers/nfc_supported_card.c @@ -1,14 +1,54 @@ #include "nfc_supported_card.h" -#include "troyka_parser.h" +#include "plantain_parser.h" +#include "troika_parser.h" +#include "plantain_4k_parser.h" +#include "troika_4k_parser.h" +#include "two_cities.h" +#include "all_in_one.h" NfcSupportedCard nfc_supported_card[NfcSupportedCardTypeEnd] = { - [NfcSupportedCardTypeTroyka] = + [NfcSupportedCardTypePlantain] = { .protocol = NfcDeviceProtocolMifareClassic, - .verify = troyka_parser_verify, - .read = troyka_parser_read, - .parse = troyka_parser_parse, + .verify = plantain_parser_verify, + .read = plantain_parser_read, + .parse = plantain_parser_parse, + }, + [NfcSupportedCardTypeTroika] = + { + .protocol = NfcDeviceProtocolMifareClassic, + .verify = troika_parser_verify, + .read = troika_parser_read, + .parse = troika_parser_parse, + }, + [NfcSupportedCardTypePlantain4K] = + { + .protocol = NfcDeviceProtocolMifareClassic, + .verify = plantain_4k_parser_verify, + .read = plantain_4k_parser_read, + .parse = plantain_4k_parser_parse, + }, + [NfcSupportedCardTypeTroika4K] = + { + .protocol = NfcDeviceProtocolMifareClassic, + .verify = troika_4k_parser_verify, + .read = troika_4k_parser_read, + .parse = troika_4k_parser_parse, + }, + [NfcSupportedCardTypeTwoCities] = + { + .protocol = NfcDeviceProtocolMifareClassic, + .verify = two_cities_parser_verify, + .read = two_cities_parser_read, + .parse = two_cities_parser_parse, + }, + [NfcSupportedCardTypeAllInOne] = + { + .protocol = NfcDeviceProtocolMifareUl, + .verify = all_in_one_parser_verify, + .read = all_in_one_parser_read, + .parse = all_in_one_parser_parse, }, }; diff --git a/lib/nfc/parsers/nfc_supported_card.h b/lib/nfc/parsers/nfc_supported_card.h index 9b5d1c05..d34b5794 100644 --- a/lib/nfc/parsers/nfc_supported_card.h +++ b/lib/nfc/parsers/nfc_supported_card.h @@ -7,7 +7,12 @@ #include typedef enum { - NfcSupportedCardTypeTroyka, + NfcSupportedCardTypePlantain, + NfcSupportedCardTypeTroika, + NfcSupportedCardTypePlantain4K, + NfcSupportedCardTypeTroika4K, + NfcSupportedCardTypeTwoCities, + NfcSupportedCardTypeAllInOne, NfcSupportedCardTypeEnd, } NfcSupportedCardType; diff --git a/lib/nfc/parsers/plantain_4k_parser.c b/lib/nfc/parsers/plantain_4k_parser.c new file mode 100644 index 00000000..77387707 --- /dev/null +++ b/lib/nfc/parsers/plantain_4k_parser.c @@ -0,0 +1,153 @@ +#include "nfc_supported_card.h" +#include "plantain_parser.h" // For luhn and string_push_uint64 + +#include +#include + +#include "furi_hal.h" + +static const MfClassicAuthContext plantain_keys_4k[] = { + {.sector = 0, .key_a = 0xFFFFFFFFFFFF, .key_b = 0xFFFFFFFFFFFF}, + {.sector = 1, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 2, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 3, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 4, .key_a = 0xe56ac127dd45, .key_b = 0x19fc84a3784b}, + {.sector = 5, .key_a = 0x77dabc9825e1, .key_b = 0x9764fec3154a}, + {.sector = 6, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 7, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 8, .key_a = 0x26973ea74321, .key_b = 0xd27058c6e2c7}, + {.sector = 9, .key_a = 0xeb0a8ff88ade, .key_b = 0x578a9ada41e3}, + {.sector = 10, .key_a = 0xea0fd73cb149, .key_b = 0x29c35fa068fb}, + {.sector = 11, .key_a = 0xc76bf71a2509, .key_b = 0x9ba241db3f56}, + {.sector = 12, .key_a = 0xacffffffffff, .key_b = 0x71f3a315ad26}, + {.sector = 13, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 14, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 15, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 16, .key_a = 0x72f96bdd3714, .key_b = 0x462225cd34cf}, + {.sector = 17, .key_a = 0x044ce1872bc3, .key_b = 0x8c90c70cff4a}, + {.sector = 18, .key_a = 0xbc2d1791dec1, .key_b = 0xca96a487de0b}, + {.sector = 19, .key_a = 0x8791b2ccb5c4, .key_b = 0xc956c3b80da3}, + {.sector = 20, .key_a = 0x8e26e45e7d65, .key_b = 0x8e65b3af7d22}, + {.sector = 21, .key_a = 0x0f318130ed18, .key_b = 0x0c420a20e056}, + {.sector = 22, .key_a = 0x045ceca15535, .key_b = 0x31bec3d9e510}, + {.sector = 23, .key_a = 0x9d993c5d4ef4, .key_b = 0x86120e488abf}, + {.sector = 24, .key_a = 0xc65d4eaa645b, .key_b = 0xb69d40d1a439}, + {.sector = 25, .key_a = 0x3a8a139c20b4, .key_b = 0x8818a9c5d406}, + {.sector = 26, .key_a = 0xbaff3053b496, .key_b = 0x4b7cb25354d3}, + {.sector = 27, .key_a = 0x7413b599c4ea, .key_b = 0xb0a2AAF3A1BA}, + {.sector = 28, .key_a = 0x0ce7cd2cc72b, .key_b = 0xfa1fbb3f0f1f}, + {.sector = 29, .key_a = 0x0be5fac8b06a, .key_b = 0x6f95887a4fd3}, + {.sector = 30, .key_a = 0x0eb23cc8110b, .key_b = 0x04dc35277635}, + {.sector = 31, .key_a = 0xbc4580b7f20b, .key_b = 0xd0a4131fb290}, + {.sector = 32, .key_a = 0x7a396f0d633d, .key_b = 0xad2bdc097023}, + {.sector = 33, .key_a = 0xa3faa6daff67, .key_b = 0x7600e889adf9}, + {.sector = 34, .key_a = 0xfd8705e721b0, .key_b = 0x296fc317a513}, + {.sector = 35, .key_a = 0x22052b480d11, .key_b = 0xe19504c39461}, + {.sector = 36, .key_a = 0xa7141147d430, .key_b = 0xff16014fefc7}, + {.sector = 37, .key_a = 0x8a8d88151a00, .key_b = 0x038b5f9b5a2a}, + {.sector = 38, .key_a = 0xb27addfb64b0, .key_b = 0x152fd0c420a7}, + {.sector = 39, .key_a = 0x7259fa0197c6, .key_b = 0x5583698df085}, +}; + +bool plantain_4k_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { + furi_assert(nfc_worker); + UNUSED(nfc_worker); + + if(nfc_worker->dev_data->mf_classic_data.type != MfClassicType4k) { + return false; + } + + uint8_t sector = 8; + uint8_t block = mf_classic_get_sector_trailer_block_num_by_sector(sector); + FURI_LOG_D("Plant4K", "Verifying sector %d", sector); + if(mf_classic_authenticate(tx_rx, block, 0x26973ea74321, MfClassicKeyA)) { + FURI_LOG_D("Plant4K", "Sector %d verified", sector); + return true; + } + return false; +} + +bool plantain_4k_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { + furi_assert(nfc_worker); + + MfClassicReader reader = {}; + FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; + reader.type = mf_classic_get_classic_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak); + for(size_t i = 0; i < COUNT_OF(plantain_keys_4k); i++) { + mf_classic_reader_add_sector( + &reader, + plantain_keys_4k[i].sector, + plantain_keys_4k[i].key_a, + plantain_keys_4k[i].key_b); + FURI_LOG_T("plant4k", "Added sector %d", plantain_keys_4k[i].sector); + } + for(int i = 0; i < 5; i++) { + if(mf_classic_read_card(tx_rx, &reader, &nfc_worker->dev_data->mf_classic_data) == 40) { + return true; + } + } + return false; +} + +bool plantain_4k_parser_parse(NfcDeviceData* dev_data) { + MfClassicData* data = &dev_data->mf_classic_data; + + // Verify key + MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, 8); + uint64_t key = nfc_util_bytes2num(sec_tr->key_a, 6); + if(key != plantain_keys_4k[8].key_a) return false; + + // Point to block 0 of sector 4, value 0 + uint8_t* temp_ptr = &data->block[4 * 4].value[0]; + // Read first 4 bytes of block 0 of sector 4 from last to first and convert them to uint32_t + // 38 18 00 00 becomes 00 00 18 38, and equals to 6200 decimal + uint32_t balance = + ((temp_ptr[3] << 24) | (temp_ptr[2] << 16) | (temp_ptr[1] << 8) | temp_ptr[0]) / 100; + // Read card number + // Point to block 0 of sector 0, value 0 + temp_ptr = &data->block[0 * 4].value[0]; + // Read first 7 bytes of block 0 of sector 0 from last to first and convert them to uint64_t + // 80 5C 23 8A 16 31 04 becomes 04 31 16 8A 23 5C 80, and equals to 36130104729284868 decimal + uint8_t card_number_arr[7]; + for(size_t i = 0; i < 7; i++) { + card_number_arr[i] = temp_ptr[6 - i]; + } + // Copy card number to uint64_t + uint64_t card_number = 0; + for(size_t i = 0; i < 7; i++) { + card_number = (card_number << 8) | card_number_arr[i]; + } + // Convert card number to string + string_t card_number_str; + string_init(card_number_str); + // Should look like "361301047292848684" + // %llu doesn't work for some reason in sprintf, so we use string_push_uint64 instead + string_push_uint64(card_number, card_number_str); + // Add suffix with luhn checksum (1 digit) to the card number string + string_t card_number_suffix; + string_init(card_number_suffix); + + // The number to calculate the checksum on doesn't fit into uint64_t, idk + //uint8_t luhn_checksum = plantain_calculate_luhn(card_number); + + // // Convert luhn checksum to string + // string_t luhn_checksum_str; + // string_init(luhn_checksum_str); + // string_push_uint64(luhn_checksum, luhn_checksum_str); + + string_cat_printf(card_number_suffix, "-"); + // FURI_LOG_D("plant4k", "Card checksum: %d", luhn_checksum); + string_cat_printf(card_number_str, string_get_cstr(card_number_suffix)); + // Free all not needed strings + string_clear(card_number_suffix); + // string_clear(luhn_checksum_str); + + string_printf( + dev_data->parsed_data, + "\e#Plantain\nN:%s\nBalance:%d\n", + string_get_cstr(card_number_str), + balance); + string_clear(card_number_str); + + return true; +} diff --git a/lib/nfc/parsers/plantain_4k_parser.h b/lib/nfc/parsers/plantain_4k_parser.h new file mode 100644 index 00000000..29998af1 --- /dev/null +++ b/lib/nfc/parsers/plantain_4k_parser.h @@ -0,0 +1,9 @@ +#pragma once + +#include "nfc_supported_card.h" + +bool plantain_4k_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); + +bool plantain_4k_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); + +bool plantain_4k_parser_parse(NfcDeviceData* dev_data); diff --git a/lib/nfc/parsers/plantain_parser.c b/lib/nfc/parsers/plantain_parser.c new file mode 100644 index 00000000..ff81b8e9 --- /dev/null +++ b/lib/nfc/parsers/plantain_parser.c @@ -0,0 +1,147 @@ +#include "nfc_supported_card.h" + +#include +#include + +#include "furi_hal.h" + +static const MfClassicAuthContext plantain_keys[] = { + {.sector = 0, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 1, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 2, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 3, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 4, .key_a = 0xe56ac127dd45, .key_b = 0x19fc84a3784b}, + {.sector = 5, .key_a = 0x77dabc9825e1, .key_b = 0x9764fec3154a}, + {.sector = 6, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 7, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 8, .key_a = 0x26973ea74321, .key_b = 0xd27058c6e2c7}, + {.sector = 9, .key_a = 0xeb0a8ff88ade, .key_b = 0x578a9ada41e3}, + {.sector = 10, .key_a = 0xea0fd73cb149, .key_b = 0x29c35fa068fb}, + {.sector = 11, .key_a = 0xc76bf71a2509, .key_b = 0x9ba241db3f56}, + {.sector = 12, .key_a = 0xacffffffffff, .key_b = 0x71f3a315ad26}, + {.sector = 13, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 14, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 15, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, +}; + +bool plantain_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { + furi_assert(nfc_worker); + UNUSED(nfc_worker); + if(nfc_worker->dev_data->mf_classic_data.type != MfClassicType1k) { + return false; + } + + uint8_t sector = 8; + uint8_t block = mf_classic_get_sector_trailer_block_num_by_sector(sector); + FURI_LOG_D("Plant", "Verifying sector %d", sector); + if(mf_classic_authenticate(tx_rx, block, 0x26973ea74321, MfClassicKeyA)) { + FURI_LOG_D("Plant", "Sector %d verified", sector); + return true; + } + return false; +} + +bool plantain_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { + furi_assert(nfc_worker); + + MfClassicReader reader = {}; + FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; + reader.type = mf_classic_get_classic_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak); + for(size_t i = 0; i < COUNT_OF(plantain_keys); i++) { + mf_classic_reader_add_sector( + &reader, plantain_keys[i].sector, plantain_keys[i].key_a, plantain_keys[i].key_b); + } + + return mf_classic_read_card(tx_rx, &reader, &nfc_worker->dev_data->mf_classic_data) == 16; +} + +void string_push_uint64(uint64_t input, string_t output) { + const uint8_t base = 10; + + do { + char c = input % base; + input /= base; + + if(c < 10) + c += '0'; + else + c += 'A' - 10; + string_push_back(output, c); + } while(input); + + // reverse string + for(uint8_t i = 0; i < string_size(output) / 2; i++) { + char c = string_get_char(output, i); + string_set_char(output, i, string_get_char(output, string_size(output) - i - 1)); + string_set_char(output, string_size(output) - i - 1, c); + } +} + +uint8_t plantain_calculate_luhn(uint64_t number) { + // No. + UNUSED(number); + return 0; +} + +bool plantain_parser_parse(NfcDeviceData* dev_data) { + MfClassicData* data = &dev_data->mf_classic_data; + + // Verify key + MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, 8); + uint64_t key = nfc_util_bytes2num(sec_tr->key_a, 6); + if(key != plantain_keys[8].key_a) return false; + + // Point to block 0 of sector 4, value 0 + uint8_t* temp_ptr = &data->block[4 * 4].value[0]; + // Read first 4 bytes of block 0 of sector 4 from last to first and convert them to uint32_t + // 38 18 00 00 becomes 00 00 18 38, and equals to 6200 decimal + uint32_t balance = + ((temp_ptr[3] << 24) | (temp_ptr[2] << 16) | (temp_ptr[1] << 8) | temp_ptr[0]) / 100; + // Read card number + // Point to block 0 of sector 0, value 0 + temp_ptr = &data->block[0 * 4].value[0]; + // Read first 7 bytes of block 0 of sector 0 from last to first and convert them to uint64_t + // 80 5C 23 8A 16 31 04 becomes 04 31 16 8A 23 5C 80, and equals to 36130104729284868 decimal + uint8_t card_number_arr[7]; + for(size_t i = 0; i < 7; i++) { + card_number_arr[i] = temp_ptr[6 - i]; + } + // Copy card number to uint64_t + uint64_t card_number = 0; + for(size_t i = 0; i < 7; i++) { + card_number = (card_number << 8) | card_number_arr[i]; + } + // Convert card number to string + string_t card_number_str; + string_init(card_number_str); + // Should look like "361301047292848684" + // %llu doesn't work for some reason in sprintf, so we use string_push_uint64 instead + string_push_uint64(card_number, card_number_str); + // Add suffix with luhn checksum (1 digit) to the card number string + string_t card_number_suffix; + string_init(card_number_suffix); + + // The number to calculate the checksum on doesn't fit into uint64_t, idk + //uint8_t luhn_checksum = plantain_calculate_luhn(card_number); + + // // Convert luhn checksum to string + // string_t luhn_checksum_str; + // string_init(luhn_checksum_str); + // string_push_uint64(luhn_checksum, luhn_checksum_str); + + string_cat_printf(card_number_suffix, "-"); + // FURI_LOG_D("plant4k", "Card checksum: %d", luhn_checksum); + string_cat_printf(card_number_str, string_get_cstr(card_number_suffix)); + // Free all not needed strings + string_clear(card_number_suffix); + // string_clear(luhn_checksum_str); + + string_printf( + dev_data->parsed_data, + "\e#Plantain\nN:%s\nBalance:%d\n", + string_get_cstr(card_number_str), + balance); + string_clear(card_number_str); + + return true; +} diff --git a/lib/nfc/parsers/plantain_parser.h b/lib/nfc/parsers/plantain_parser.h new file mode 100644 index 00000000..d37f0dd4 --- /dev/null +++ b/lib/nfc/parsers/plantain_parser.h @@ -0,0 +1,13 @@ +#pragma once + +#include "nfc_supported_card.h" + +bool plantain_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); + +bool plantain_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); + +bool plantain_parser_parse(NfcDeviceData* dev_data); + +void string_push_uint64(uint64_t input, string_t output); + +uint8_t plantain_calculate_luhn(uint64_t number); diff --git a/lib/nfc/parsers/troika_4k_parser.c b/lib/nfc/parsers/troika_4k_parser.c new file mode 100644 index 00000000..8c32381f --- /dev/null +++ b/lib/nfc/parsers/troika_4k_parser.c @@ -0,0 +1,104 @@ +#include "nfc_supported_card.h" + +#include +#include + +static const MfClassicAuthContext troika_4k_keys[] = { + {.sector = 0, .key_a = 0xa0a1a2a3a4a5, .key_b = 0xfbf225dc5d58}, + {.sector = 1, .key_a = 0xa82607b01c0d, .key_b = 0x2910989b6880}, + {.sector = 2, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99}, + {.sector = 3, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99}, + {.sector = 4, .key_a = 0x73068f118c13, .key_b = 0x2b7f3253fac5}, + {.sector = 5, .key_a = 0xFBC2793D540B, .key_b = 0xd3a297dc2698}, + {.sector = 6, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99}, + {.sector = 7, .key_a = 0xae3d65a3dad4, .key_b = 0x0f1c63013dbb}, + {.sector = 8, .key_a = 0xa73f5dc1d333, .key_b = 0xe35173494a81}, + {.sector = 9, .key_a = 0x69a32f1c2f19, .key_b = 0x6b8bd9860763}, + {.sector = 10, .key_a = 0x9becdf3d9273, .key_b = 0xf8493407799d}, + {.sector = 11, .key_a = 0x08b386463229, .key_b = 0x5efbaecef46b}, + {.sector = 12, .key_a = 0xcd4c61c26e3d, .key_b = 0x31c7610de3b0}, + {.sector = 13, .key_a = 0xa82607b01c0d, .key_b = 0x2910989b6880}, + {.sector = 14, .key_a = 0x0e8f64340ba4, .key_b = 0x4acec1205d75}, + {.sector = 15, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99}, + {.sector = 16, .key_a = 0x6b02733bb6ec, .key_b = 0x7038cd25c408}, + {.sector = 17, .key_a = 0x403d706ba880, .key_b = 0xb39d19a280df}, + {.sector = 18, .key_a = 0xc11f4597efb5, .key_b = 0x70d901648cb9}, + {.sector = 19, .key_a = 0x0db520c78c1c, .key_b = 0x73e5b9d9d3a4}, + {.sector = 20, .key_a = 0x3ebce0925b2f, .key_b = 0x372cc880f216}, + {.sector = 21, .key_a = 0x16a27af45407, .key_b = 0x9868925175ba}, + {.sector = 22, .key_a = 0xaba208516740, .key_b = 0xce26ecb95252}, + {.sector = 23, .key_a = 0xCD64E567ABCD, .key_b = 0x8f79c4fd8a01}, + {.sector = 24, .key_a = 0x764cd061f1e6, .key_b = 0xa74332f74994}, + {.sector = 25, .key_a = 0x1cc219e9fec1, .key_b = 0xb90de525ceb6}, + {.sector = 26, .key_a = 0x2fe3cb83ea43, .key_b = 0xfba88f109b32}, + {.sector = 27, .key_a = 0x07894ffec1d6, .key_b = 0xefcb0e689db3}, + {.sector = 28, .key_a = 0x04c297b91308, .key_b = 0xc8454c154cb5}, + {.sector = 29, .key_a = 0x7a38e3511a38, .key_b = 0xab16584c972a}, + {.sector = 30, .key_a = 0x7545df809202, .key_b = 0xecf751084a80}, + {.sector = 31, .key_a = 0x5125974cd391, .key_b = 0xd3eafb5df46d}, + {.sector = 32, .key_a = 0x7a86aa203788, .key_b = 0xe41242278ca2}, + {.sector = 33, .key_a = 0xafcef64c9913, .key_b = 0x9db96dca4324}, + {.sector = 34, .key_a = 0x04eaa462f70b, .key_b = 0xac17b93e2fae}, + {.sector = 35, .key_a = 0xe734c210f27e, .key_b = 0x29ba8c3e9fda}, + {.sector = 36, .key_a = 0xd5524f591eed, .key_b = 0x5daf42861b4d}, + {.sector = 37, .key_a = 0xe4821a377b75, .key_b = 0xe8709e486465}, + {.sector = 38, .key_a = 0x518dc6eea089, .key_b = 0x97c64ac98ca4}, + {.sector = 39, .key_a = 0xbb52f8cce07f, .key_b = 0x6b6119752c70}, +}; + +bool troika_4k_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { + furi_assert(nfc_worker); + + if(nfc_worker->dev_data->mf_classic_data.type != MfClassicType4k) { + return false; + } + + uint8_t sector = 11; + uint8_t block = mf_classic_get_sector_trailer_block_num_by_sector(sector); + FURI_LOG_D("Troika", "Verifying sector %d", sector); + if(mf_classic_authenticate(tx_rx, block, 0x08b386463229, MfClassicKeyA)) { + FURI_LOG_D("Troika", "Sector %d verified", sector); + return true; + } + return false; +} + +bool troika_4k_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { + furi_assert(nfc_worker); + + MfClassicReader reader = {}; + FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; + reader.type = mf_classic_get_classic_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak); + for(size_t i = 0; i < COUNT_OF(troika_4k_keys); i++) { + mf_classic_reader_add_sector( + &reader, troika_4k_keys[i].sector, troika_4k_keys[i].key_a, troika_4k_keys[i].key_b); + } + + return mf_classic_read_card(tx_rx, &reader, &nfc_worker->dev_data->mf_classic_data) == 40; +} + +bool troika_4k_parser_parse(NfcDeviceData* dev_data) { + MfClassicData* data = &dev_data->mf_classic_data; + + // Verify key + MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, 4); + uint64_t key = nfc_util_bytes2num(sec_tr->key_a, 6); + if(key != troika_4k_keys[4].key_a) return false; + + // Verify card type + if(data->type != MfClassicType4k) return false; + + uint8_t* temp_ptr = &data->block[8 * 4 + 1].value[5]; + uint16_t balance = ((temp_ptr[0] << 8) | temp_ptr[1]) / 25; + temp_ptr = &data->block[8 * 4].value[3]; + uint32_t number = 0; + for(size_t i = 0; i < 4; i++) { + number <<= 8; + number |= temp_ptr[i]; + } + number >>= 4; + + string_printf(dev_data->parsed_data, "\e#Troika\nNum: %ld\nBalance: %d rur.", number, balance); + + return true; +} diff --git a/lib/nfc/parsers/troika_4k_parser.h b/lib/nfc/parsers/troika_4k_parser.h new file mode 100644 index 00000000..c1d6f01d --- /dev/null +++ b/lib/nfc/parsers/troika_4k_parser.h @@ -0,0 +1,9 @@ +#pragma once + +#include "nfc_supported_card.h" + +bool troika_4k_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); + +bool troika_4k_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); + +bool troika_4k_parser_parse(NfcDeviceData* dev_data); diff --git a/lib/nfc/parsers/troyka_parser.c b/lib/nfc/parsers/troika_parser.c similarity index 68% rename from lib/nfc/parsers/troyka_parser.c rename to lib/nfc/parsers/troika_parser.c index 51ffa42e..f396b168 100644 --- a/lib/nfc/parsers/troyka_parser.c +++ b/lib/nfc/parsers/troika_parser.c @@ -3,7 +3,7 @@ #include #include -static const MfClassicAuthContext troyka_keys[] = { +static const MfClassicAuthContext troika_keys[] = { {.sector = 0, .key_a = 0xa0a1a2a3a4a5, .key_b = 0xfbf225dc5d58}, {.sector = 1, .key_a = 0xa82607b01c0d, .key_b = 0x2910989b6880}, {.sector = 2, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99}, @@ -22,42 +22,50 @@ static const MfClassicAuthContext troyka_keys[] = { {.sector = 15, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99}, }; -bool troyka_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { +bool troika_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { furi_assert(nfc_worker); UNUSED(nfc_worker); + if(nfc_worker->dev_data->mf_classic_data.type != MfClassicType1k) { + return false; + } - MfClassicAuthContext auth_ctx = { - .key_a = MF_CLASSIC_NO_KEY, - .key_b = MF_CLASSIC_NO_KEY, - .sector = 8, - }; - return mf_classic_auth_attempt(tx_rx, &auth_ctx, 0xa73f5dc1d333); + uint8_t sector = 11; + uint8_t block = mf_classic_get_sector_trailer_block_num_by_sector(sector); + FURI_LOG_D("Troika", "Verifying sector %d", sector); + if(mf_classic_authenticate(tx_rx, block, 0x08b386463229, MfClassicKeyA)) { + FURI_LOG_D("Troika", "Sector %d verified", sector); + return true; + } + return false; } -bool troyka_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { +bool troika_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { furi_assert(nfc_worker); MfClassicReader reader = {}; FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; reader.type = mf_classic_get_classic_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak); - for(size_t i = 0; i < COUNT_OF(troyka_keys); i++) { + for(size_t i = 0; i < COUNT_OF(troika_keys); i++) { mf_classic_reader_add_sector( - &reader, troyka_keys[i].sector, troyka_keys[i].key_a, troyka_keys[i].key_b); + &reader, troika_keys[i].sector, troika_keys[i].key_a, troika_keys[i].key_b); } return mf_classic_read_card(tx_rx, &reader, &nfc_worker->dev_data->mf_classic_data) == 16; } -bool troyka_parser_parse(NfcDeviceData* dev_data) { +bool troika_parser_parse(NfcDeviceData* dev_data) { MfClassicData* data = &dev_data->mf_classic_data; - bool troyka_parsed = false; + bool troika_parsed = false; do { // Verify key MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, 8); uint64_t key = nfc_util_bytes2num(sec_tr->key_a, 6); - if(key != troyka_keys[8].key_a) break; + if(key != troika_keys[8].key_a) break; + + // Verify card type + if(data->type != MfClassicType1k) break; // Parse data uint8_t* temp_ptr = &data->block[8 * 4 + 1].value[5]; @@ -71,9 +79,9 @@ bool troyka_parser_parse(NfcDeviceData* dev_data) { number >>= 4; string_printf( - dev_data->parsed_data, "\e#Troyka\nNum: %ld\nBalance: %d rur.", number, balance); - troyka_parsed = true; + dev_data->parsed_data, "\e#Troika\nNum: %ld\nBalance: %d rur.", number, balance); + troika_parsed = true; } while(false); - return troyka_parsed; + return troika_parsed; } diff --git a/lib/nfc/parsers/troika_parser.h b/lib/nfc/parsers/troika_parser.h new file mode 100644 index 00000000..2aae48d2 --- /dev/null +++ b/lib/nfc/parsers/troika_parser.h @@ -0,0 +1,9 @@ +#pragma once + +#include "nfc_supported_card.h" + +bool troika_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); + +bool troika_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); + +bool troika_parser_parse(NfcDeviceData* dev_data); diff --git a/lib/nfc/parsers/troyka_parser.h b/lib/nfc/parsers/troyka_parser.h deleted file mode 100644 index 445fe40e..00000000 --- a/lib/nfc/parsers/troyka_parser.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "nfc_supported_card.h" - -bool troyka_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); - -bool troyka_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); - -bool troyka_parser_parse(NfcDeviceData* dev_data); diff --git a/lib/nfc/parsers/two_cities.c b/lib/nfc/parsers/two_cities.c new file mode 100644 index 00000000..d052dff1 --- /dev/null +++ b/lib/nfc/parsers/two_cities.c @@ -0,0 +1,171 @@ +#include "nfc_supported_card.h" +#include "plantain_parser.h" // For plantain-specific stuff + +#include +#include + +#include "furi_hal.h" + +static const MfClassicAuthContext two_cities_keys_4k[] = { + {.sector = 0, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 1, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 2, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99}, + {.sector = 3, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99}, + {.sector = 4, .key_a = 0xe56ac127dd45, .key_b = 0x19fc84a3784b}, + {.sector = 5, .key_a = 0x77dabc9825e1, .key_b = 0x9764fec3154a}, + {.sector = 6, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99}, + {.sector = 7, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 8, .key_a = 0xa73f5dc1d333, .key_b = 0xe35173494a81}, + {.sector = 9, .key_a = 0x69a32f1c2f19, .key_b = 0x6b8bd9860763}, + {.sector = 10, .key_a = 0xea0fd73cb149, .key_b = 0x29c35fa068fb}, + {.sector = 11, .key_a = 0xc76bf71a2509, .key_b = 0x9ba241db3f56}, + {.sector = 12, .key_a = 0xacffffffffff, .key_b = 0x71f3a315ad26}, + {.sector = 13, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 14, .key_a = 0xffffffffffff, .key_b = 0xffffffffffff}, + {.sector = 15, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99}, + {.sector = 16, .key_a = 0x72f96bdd3714, .key_b = 0x462225cd34cf}, + {.sector = 17, .key_a = 0x044ce1872bc3, .key_b = 0x8c90c70cff4a}, + {.sector = 18, .key_a = 0xbc2d1791dec1, .key_b = 0xca96a487de0b}, + {.sector = 19, .key_a = 0x8791b2ccb5c4, .key_b = 0xc956c3b80da3}, + {.sector = 20, .key_a = 0x8e26e45e7d65, .key_b = 0x8e65b3af7d22}, + {.sector = 21, .key_a = 0x0f318130ed18, .key_b = 0x0c420a20e056}, + {.sector = 22, .key_a = 0x045ceca15535, .key_b = 0x31bec3d9e510}, + {.sector = 23, .key_a = 0x9d993c5d4ef4, .key_b = 0x86120e488abf}, + {.sector = 24, .key_a = 0xc65d4eaa645b, .key_b = 0xb69d40d1a439}, + {.sector = 25, .key_a = 0x3a8a139c20b4, .key_b = 0x8818a9c5d406}, + {.sector = 26, .key_a = 0xbaff3053b496, .key_b = 0x4b7cb25354d3}, + {.sector = 27, .key_a = 0x7413b599c4ea, .key_b = 0xb0a2AAF3A1BA}, + {.sector = 28, .key_a = 0x0ce7cd2cc72b, .key_b = 0xfa1fbb3f0f1f}, + {.sector = 29, .key_a = 0x0be5fac8b06a, .key_b = 0x6f95887a4fd3}, + {.sector = 30, .key_a = 0x26973ea74321, .key_b = 0xd27058c6e2c7}, + {.sector = 31, .key_a = 0xeb0a8ff88ade, .key_b = 0x578a9ada41e3}, + {.sector = 32, .key_a = 0x7a396f0d633d, .key_b = 0xad2bdc097023}, + {.sector = 33, .key_a = 0xa3faa6daff67, .key_b = 0x7600e889adf9}, + {.sector = 34, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99}, + {.sector = 35, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99}, + {.sector = 36, .key_a = 0xa7141147d430, .key_b = 0xff16014fefc7}, + {.sector = 37, .key_a = 0x8a8d88151a00, .key_b = 0x038b5f9b5a2a}, + {.sector = 38, .key_a = 0xb27addfb64b0, .key_b = 0x152fd0c420a7}, + {.sector = 39, .key_a = 0x7259fa0197c6, .key_b = 0x5583698df085}, +}; + +bool two_cities_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { + furi_assert(nfc_worker); + UNUSED(nfc_worker); + + if(nfc_worker->dev_data->mf_classic_data.type != MfClassicType4k) { + return false; + } + + uint8_t sector = 4; + uint8_t block = mf_classic_get_sector_trailer_block_num_by_sector(sector); + FURI_LOG_D("2cities", "Verifying sector %d", sector); + if(mf_classic_authenticate(tx_rx, block, 0xe56ac127dd45, MfClassicKeyA)) { + FURI_LOG_D("2cities", "Sector %d verified", sector); + return true; + } + return false; +} + +bool two_cities_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { + furi_assert(nfc_worker); + + MfClassicReader reader = {}; + FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; + reader.type = mf_classic_get_classic_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak); + for(size_t i = 0; i < COUNT_OF(two_cities_keys_4k); i++) { + mf_classic_reader_add_sector( + &reader, + two_cities_keys_4k[i].sector, + two_cities_keys_4k[i].key_a, + two_cities_keys_4k[i].key_b); + FURI_LOG_T("2cities", "Added sector %d", two_cities_keys_4k[i].sector); + } + + return mf_classic_read_card(tx_rx, &reader, &nfc_worker->dev_data->mf_classic_data) == 40; +} + +bool two_cities_parser_parse(NfcDeviceData* dev_data) { + MfClassicData* data = &dev_data->mf_classic_data; + + // Verify key + MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, 4); + uint64_t key = nfc_util_bytes2num(sec_tr->key_a, 6); + if(key != two_cities_keys_4k[4].key_a) return false; + + // ===== + // PLANTAIN + // ===== + + // Point to block 0 of sector 4, value 0 + uint8_t* temp_ptr = &data->block[4 * 4].value[0]; + // Read first 4 bytes of block 0 of sector 4 from last to first and convert them to uint32_t + // 38 18 00 00 becomes 00 00 18 38, and equals to 6200 decimal + uint32_t balance = + ((temp_ptr[3] << 24) | (temp_ptr[2] << 16) | (temp_ptr[1] << 8) | temp_ptr[0]) / 100; + // Read card number + // Point to block 0 of sector 0, value 0 + temp_ptr = &data->block[0 * 4].value[0]; + // Read first 7 bytes of block 0 of sector 0 from last to first and convert them to uint64_t + // 80 5C 23 8A 16 31 04 becomes 04 31 16 8A 23 5C 80, and equals to 36130104729284868 decimal + uint8_t card_number_arr[7]; + for(size_t i = 0; i < 7; i++) { + card_number_arr[i] = temp_ptr[6 - i]; + } + // Copy card number to uint64_t + uint64_t card_number = 0; + for(size_t i = 0; i < 7; i++) { + card_number = (card_number << 8) | card_number_arr[i]; + } + // Convert card number to string + string_t card_number_str; + string_init(card_number_str); + // Should look like "361301047292848684" + // %llu doesn't work for some reason in sprintf, so we use string_push_uint64 instead + string_push_uint64(card_number, card_number_str); + // Add suffix with luhn checksum (1 digit) to the card number string + string_t card_number_suffix; + string_init(card_number_suffix); + + // The number to calculate the checksum on doesn't fit into uint64_t, idk + //uint8_t luhn_checksum = two_cities_calculate_luhn(card_number); + + // // Convert luhn checksum to string + // string_t luhn_checksum_str; + // string_init(luhn_checksum_str); + // string_push_uint64(luhn_checksum, luhn_checksum_str); + + string_cat_printf(card_number_suffix, "-"); + // FURI_LOG_D("plant4k", "Card checksum: %d", luhn_checksum); + string_cat_printf(card_number_str, string_get_cstr(card_number_suffix)); + // Free all not needed strings + string_clear(card_number_suffix); + // string_clear(luhn_checksum_str); + + // ===== + // --PLANTAIN-- + // ===== + // TROIKA + // ===== + + uint8_t* troika_temp_ptr = &data->block[8 * 4 + 1].value[5]; + uint16_t troika_balance = ((troika_temp_ptr[0] << 8) | troika_temp_ptr[1]) / 25; + troika_temp_ptr = &data->block[8 * 4].value[3]; + uint32_t troika_number = 0; + for(size_t i = 0; i < 4; i++) { + troika_number <<= 8; + troika_number |= troika_temp_ptr[i]; + } + troika_number >>= 4; + + string_printf( + dev_data->parsed_data, + "\e#Troika+Plantain\nPN: %s\nPB: %d rur.\nTN: %d\nTB: %d rur.\n", + string_get_cstr(card_number_str), + balance, + troika_number, + troika_balance); + string_clear(card_number_str); + + return true; +} diff --git a/lib/nfc/parsers/two_cities.h b/lib/nfc/parsers/two_cities.h new file mode 100644 index 00000000..e735bea8 --- /dev/null +++ b/lib/nfc/parsers/two_cities.h @@ -0,0 +1,9 @@ +#pragma once + +#include "nfc_supported_card.h" + +bool two_cities_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); + +bool two_cities_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); + +bool two_cities_parser_parse(NfcDeviceData* dev_data); diff --git a/lib/print/SConscript b/lib/print/SConscript index 412d17a6..d4a55ab8 100644 --- a/lib/print/SConscript +++ b/lib/print/SConscript @@ -96,6 +96,12 @@ for wrapped_fn in wrapped_fn_list: ] ) +env.Append( + SDK_HEADERS=[ + File("#/lib/print/wrappers.h"), + ], +) + libenv = env.Clone(FW_LIB_NAME="print") libenv.ApplyLibFlags() libenv.Append(CCFLAGS=["-Wno-double-promotion"]) diff --git a/lib/print/wrappers.c b/lib/print/wrappers.c index 3fe44665..5cfe1060 100644 --- a/lib/print/wrappers.c +++ b/lib/print/wrappers.c @@ -1,11 +1,10 @@ -#include -#include +#include "wrappers.h" + #include #include #include #include #include -#include #include "printf_tiny.h" void _putchar(char character) { diff --git a/lib/print/wrappers.h b/lib/print/wrappers.h new file mode 100644 index 00000000..b6f0f004 --- /dev/null +++ b/lib/print/wrappers.h @@ -0,0 +1,25 @@ +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void _putchar(char character); +int __wrap_printf(const char* format, ...); +int __wrap_vsnprintf(char* str, size_t size, const char* format, va_list args); +int __wrap_puts(const char* str); +int __wrap_putchar(int ch); +int __wrap_putc(int ch, FILE* stream); +int __wrap_snprintf(char* str, size_t size, const char* format, ...); +int __wrap_fflush(FILE* stream); + +__attribute__((__noreturn__)) void __wrap___assert(const char* file, int line, const char* e); + +__attribute__((__noreturn__)) void + __wrap___assert_func(const char* file, int line, const char* func, const char* e); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/subghz/SConscript b/lib/subghz/SConscript index 3c6728af..eff2f168 100644 --- a/lib/subghz/SConscript +++ b/lib/subghz/SConscript @@ -4,6 +4,14 @@ env.Append( CPPPATH=[ "#/lib/subghz", ], + SDK_HEADERS=[ + File("#/lib/subghz/environment.h"), + File("#/lib/subghz/receiver.h"), + File("#/lib/subghz/subghz_worker.h"), + File("#/lib/subghz/subghz_tx_rx_worker.h"), + File("#/lib/subghz/transmitter.h"), + File("#/lib/subghz/protocols/raw.h"), + ], ) libenv = env.Clone(FW_LIB_NAME="subghz") diff --git a/lib/subghz/environment.h b/lib/subghz/environment.h index b8e73e33..d4678e41 100644 --- a/lib/subghz/environment.h +++ b/lib/subghz/environment.h @@ -4,6 +4,10 @@ #include "subghz_keystore.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct SubGhzEnvironment SubGhzEnvironment; /** @@ -64,3 +68,7 @@ void subghz_environment_set_nice_flor_s_rainbow_table_file_name( */ const char* subghz_environment_get_nice_flor_s_rainbow_table_file_name(SubGhzEnvironment* instance); + +#ifdef __cplusplus +} +#endif diff --git a/lib/subghz/protocols/base.h b/lib/subghz/protocols/base.h index a1a7478d..fdd13567 100644 --- a/lib/subghz/protocols/base.h +++ b/lib/subghz/protocols/base.h @@ -2,6 +2,10 @@ #include "../types.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct SubGhzProtocolDecoderBase SubGhzProtocolDecoderBase; typedef void ( @@ -77,3 +81,7 @@ struct SubGhzProtocolEncoderBase { // Callback section }; + +#ifdef __cplusplus +} +#endif diff --git a/lib/subghz/protocols/bett.c b/lib/subghz/protocols/bett.c index 08080dc6..c8070257 100644 --- a/lib/subghz/protocols/bett.c +++ b/lib/subghz/protocols/bett.c @@ -173,7 +173,7 @@ bool subghz_protocol_encoder_bett_deserialize(void* context, FlipperFormat* flip flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_bett_get_upload(instance); + if(!subghz_protocol_encoder_bett_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/came.c b/lib/subghz/protocols/came.c index 14c66b7f..53d3d078 100644 --- a/lib/subghz/protocols/came.c +++ b/lib/subghz/protocols/came.c @@ -162,7 +162,7 @@ bool subghz_protocol_encoder_came_deserialize(void* context, FlipperFormat* flip flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_came_get_upload(instance); + if(!subghz_protocol_encoder_came_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/chamberlain_code.c b/lib/subghz/protocols/chamberlain_code.c index 51f2bcd3..66d230d1 100644 --- a/lib/subghz/protocols/chamberlain_code.c +++ b/lib/subghz/protocols/chamberlain_code.c @@ -155,7 +155,7 @@ static bool break; default: - furi_crash(TAG " unknown protocol."); + FURI_LOG_E(TAG, "Invalid bits count"); return false; break; } @@ -224,7 +224,7 @@ bool subghz_protocol_encoder_chamb_code_deserialize(void* context, FlipperFormat flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_chamb_code_get_upload(instance); + if(!subghz_protocol_encoder_chamb_code_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/clemsa.c b/lib/subghz/protocols/clemsa.c index 357a0b06..33734693 100644 --- a/lib/subghz/protocols/clemsa.c +++ b/lib/subghz/protocols/clemsa.c @@ -173,7 +173,7 @@ bool subghz_protocol_encoder_clemsa_deserialize(void* context, FlipperFormat* fl flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_clemsa_get_upload(instance); + if(!subghz_protocol_encoder_clemsa_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/doitrand.c b/lib/subghz/protocols/doitrand.c index 9a0a5819..9122c193 100644 --- a/lib/subghz/protocols/doitrand.c +++ b/lib/subghz/protocols/doitrand.c @@ -154,7 +154,7 @@ bool subghz_protocol_encoder_doitrand_deserialize(void* context, FlipperFormat* flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_doitrand_get_upload(instance); + if(!subghz_protocol_encoder_doitrand_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/gate_tx.c b/lib/subghz/protocols/gate_tx.c index d7efb386..56c224ae 100644 --- a/lib/subghz/protocols/gate_tx.c +++ b/lib/subghz/protocols/gate_tx.c @@ -147,7 +147,7 @@ bool subghz_protocol_encoder_gate_tx_deserialize(void* context, FlipperFormat* f flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_gate_tx_get_upload(instance); + if(!subghz_protocol_encoder_gate_tx_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/holtek.c b/lib/subghz/protocols/holtek.c index 137ba85d..5cd16063 100644 --- a/lib/subghz/protocols/holtek.c +++ b/lib/subghz/protocols/holtek.c @@ -160,7 +160,7 @@ bool subghz_protocol_encoder_holtek_deserialize(void* context, FlipperFormat* fl flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_holtek_get_upload(instance); + if(!subghz_protocol_encoder_holtek_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/honeywell_wdb.c b/lib/subghz/protocols/honeywell_wdb.c index e1e21426..451a13f5 100644 --- a/lib/subghz/protocols/honeywell_wdb.c +++ b/lib/subghz/protocols/honeywell_wdb.c @@ -162,7 +162,7 @@ bool subghz_protocol_encoder_honeywell_wdb_deserialize( flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_honeywell_wdb_get_upload(instance); + if(!subghz_protocol_encoder_honeywell_wdb_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/hormann.c b/lib/subghz/protocols/hormann.c index 0197f59e..d78bc927 100644 --- a/lib/subghz/protocols/hormann.c +++ b/lib/subghz/protocols/hormann.c @@ -163,7 +163,7 @@ bool subghz_protocol_encoder_hormann_deserialize(void* context, FlipperFormat* f flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_hormann_get_upload(instance); + if(!subghz_protocol_encoder_hormann_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/intertechno_v3.c b/lib/subghz/protocols/intertechno_v3.c index e70bb8c8..ffe52e87 100644 --- a/lib/subghz/protocols/intertechno_v3.c +++ b/lib/subghz/protocols/intertechno_v3.c @@ -179,7 +179,7 @@ bool subghz_protocol_encoder_intertechno_v3_deserialize( flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_intertechno_v3_get_upload(instance); + if(!subghz_protocol_encoder_intertechno_v3_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index 88738f3f..99b3c5fb 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -280,7 +280,7 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_keeloq_get_upload(instance, instance->generic.btn); + if(!subghz_protocol_encoder_keeloq_get_upload(instance, instance->generic.btn)) break; if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); @@ -407,7 +407,7 @@ void subghz_protocol_decoder_keeloq_feed(void* context, bool level, uint32_t dur (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_keeloq_const.te_short) < subghz_protocol_keeloq_const.te_delta) && (DURATION_DIFF(duration, subghz_protocol_keeloq_const.te_long) < - subghz_protocol_keeloq_const.te_delta)) { + subghz_protocol_keeloq_const.te_delta * 2)) { if(instance->decoder.decode_count_bit < subghz_protocol_keeloq_const.min_count_bit_for_found) { subghz_protocol_blocks_add_bit(&instance->decoder, 1); @@ -415,7 +415,7 @@ void subghz_protocol_decoder_keeloq_feed(void* context, bool level, uint32_t dur instance->decoder.parser_step = KeeloqDecoderStepSaveDuration; } else if( (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_keeloq_const.te_long) < - subghz_protocol_keeloq_const.te_delta) && + subghz_protocol_keeloq_const.te_delta * 2) && (DURATION_DIFF(duration, subghz_protocol_keeloq_const.te_short) < subghz_protocol_keeloq_const.te_delta)) { if(instance->decoder.decode_count_bit < diff --git a/lib/subghz/protocols/linear.c b/lib/subghz/protocols/linear.c index 92ba02a8..8f7aed79 100644 --- a/lib/subghz/protocols/linear.c +++ b/lib/subghz/protocols/linear.c @@ -165,7 +165,7 @@ bool subghz_protocol_encoder_linear_deserialize(void* context, FlipperFormat* fl flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_linear_get_upload(instance); + if(!subghz_protocol_encoder_linear_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/magellen.c b/lib/subghz/protocols/magellen.c index bb0600a7..52ef5a72 100644 --- a/lib/subghz/protocols/magellen.c +++ b/lib/subghz/protocols/magellen.c @@ -168,7 +168,7 @@ bool subghz_protocol_encoder_magellen_deserialize(void* context, FlipperFormat* flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_magellen_get_upload(instance); + if(!subghz_protocol_encoder_magellen_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/megacode.c b/lib/subghz/protocols/megacode.c index 909e7217..1501580d 100644 --- a/lib/subghz/protocols/megacode.c +++ b/lib/subghz/protocols/megacode.c @@ -193,7 +193,7 @@ bool subghz_protocol_encoder_megacode_deserialize(void* context, FlipperFormat* flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_megacode_get_upload(instance); + if(!subghz_protocol_encoder_megacode_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/nero_radio.c b/lib/subghz/protocols/nero_radio.c index 69326f5a..b5a7e8c0 100644 --- a/lib/subghz/protocols/nero_radio.c +++ b/lib/subghz/protocols/nero_radio.c @@ -172,7 +172,7 @@ bool subghz_protocol_encoder_nero_radio_deserialize(void* context, FlipperFormat flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_nero_radio_get_upload(instance); + if(!subghz_protocol_encoder_nero_radio_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/nero_sketch.c b/lib/subghz/protocols/nero_sketch.c index c93b36a5..66ee569c 100644 --- a/lib/subghz/protocols/nero_sketch.c +++ b/lib/subghz/protocols/nero_sketch.c @@ -166,7 +166,7 @@ bool subghz_protocol_encoder_nero_sketch_deserialize(void* context, FlipperForma flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_nero_sketch_get_upload(instance); + if(!subghz_protocol_encoder_nero_sketch_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/nice_flo.c b/lib/subghz/protocols/nice_flo.c index 07b18e3e..f07e9efc 100644 --- a/lib/subghz/protocols/nice_flo.c +++ b/lib/subghz/protocols/nice_flo.c @@ -149,7 +149,7 @@ bool subghz_protocol_encoder_nice_flo_deserialize(void* context, FlipperFormat* flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_nice_flo_get_upload(instance); + if(!subghz_protocol_encoder_nice_flo_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/oregon2.c b/lib/subghz/protocols/oregon2.c new file mode 100644 index 00000000..84bb38be --- /dev/null +++ b/lib/subghz/protocols/oregon2.c @@ -0,0 +1,324 @@ +#include "oregon2.h" +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" +#include +#include +#include + +#define TAG "SubGhzProtocolOregon2" + +static const SubGhzBlockConst oregon2_const = { + .te_long = 1000, + .te_short = 500, + .te_delta = 200, + .min_count_bit_for_found = 32, +}; + +#define OREGON2_PREAMBLE_BITS 19 +#define OREGON2_PREAMBLE_MASK ((1 << (OREGON2_PREAMBLE_BITS + 1)) - 1) +#define OREGON2_SENSOR_ID(d) (((d) >> 16) & 0xFFFF) +#define OREGON2_CHECKSUM_BITS 8 + +// 15 ones + 0101 (inverted A) +#define OREGON2_PREAMBLE 0b1111111111111110101 + +// bit indicating the low battery +#define OREGON2_FLAG_BAT_LOW 0x4 + +struct SubGhzProtocolDecoderOregon2 { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + ManchesterState manchester_state; + bool prev_bit; + bool have_bit; + + uint8_t var_bits; + uint32_t var_data; +}; + +typedef struct SubGhzProtocolDecoderOregon2 SubGhzProtocolDecoderOregon2; + +typedef enum { + Oregon2DecoderStepReset = 0, + Oregon2DecoderStepFoundPreamble, + Oregon2DecoderStepVarData, +} Oregon2DecoderStep; + +void* subghz_protocol_decoder_oregon2_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderOregon2* instance = malloc(sizeof(SubGhzProtocolDecoderOregon2)); + instance->base.protocol = &subghz_protocol_oregon2; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_oregon2_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderOregon2* instance = context; + free(instance); +} + +void subghz_protocol_decoder_oregon2_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderOregon2* instance = context; + instance->decoder.parser_step = Oregon2DecoderStepReset; + instance->decoder.decode_data = 0UL; + instance->decoder.decode_count_bit = 0; + manchester_advance( + instance->manchester_state, ManchesterEventReset, &instance->manchester_state, NULL); + instance->have_bit = false; + instance->var_data = 0; + instance->var_bits = 0; +} + +static ManchesterEvent level_and_duration_to_event(bool level, uint32_t duration) { + bool is_long = false; + + if(DURATION_DIFF(duration, oregon2_const.te_long) < oregon2_const.te_delta) { + is_long = true; + } else if(DURATION_DIFF(duration, oregon2_const.te_short) < oregon2_const.te_delta) { + is_long = false; + } else { + return ManchesterEventReset; + } + + if(level) + return is_long ? ManchesterEventLongHigh : ManchesterEventShortHigh; + else + return is_long ? ManchesterEventLongLow : ManchesterEventShortLow; +} + +// From sensor id code return amount of bits in variable section +static uint8_t oregon2_sensor_id_var_bits(uint16_t sensor_id) { + if(sensor_id == 0xEC40) return 16; + return 0; +} + +void subghz_protocol_decoder_oregon2_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderOregon2* instance = context; + // oregon v2.1 signal is inverted + ManchesterEvent event = level_and_duration_to_event(!level, duration); + bool data; + + // low-level bit sequence decoding + if(event == ManchesterEventReset) { + instance->decoder.parser_step = Oregon2DecoderStepReset; + instance->have_bit = false; + instance->decoder.decode_data = 0UL; + instance->decoder.decode_count_bit = 0; + } + if(manchester_advance(instance->manchester_state, event, &instance->manchester_state, &data)) { + if(instance->have_bit) { + if(!instance->prev_bit && data) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + } else if(instance->prev_bit && !data) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + } else { + subghz_protocol_decoder_oregon2_reset(context); + } + instance->have_bit = false; + } else { + instance->prev_bit = data; + instance->have_bit = true; + } + } + + switch(instance->decoder.parser_step) { + case Oregon2DecoderStepReset: + // waiting for fixed oregon2 preamble + if(instance->decoder.decode_count_bit >= OREGON2_PREAMBLE_BITS && + ((instance->decoder.decode_data & OREGON2_PREAMBLE_MASK) == OREGON2_PREAMBLE)) { + instance->decoder.parser_step = Oregon2DecoderStepFoundPreamble; + instance->decoder.decode_count_bit = 0; + instance->decoder.decode_data = 0UL; + } + break; + case Oregon2DecoderStepFoundPreamble: + // waiting for fixed oregon2 data + if(instance->decoder.decode_count_bit == 32) { + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + instance->decoder.decode_data = 0UL; + instance->decoder.decode_count_bit = 0; + + // reverse nibbles in decoded data + instance->generic.data = (instance->generic.data & 0x55555555) << 1 | + (instance->generic.data & 0xAAAAAAAA) >> 1; + instance->generic.data = (instance->generic.data & 0x33333333) << 2 | + (instance->generic.data & 0xCCCCCCCC) >> 2; + + instance->var_bits = + oregon2_sensor_id_var_bits(OREGON2_SENSOR_ID(instance->generic.data)); + + if(!instance->var_bits) { + // sensor is not supported, stop decoding, but showing the decoded fixed part + instance->decoder.parser_step = Oregon2DecoderStepReset; + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } else { + instance->decoder.parser_step = Oregon2DecoderStepVarData; + } + } + break; + case Oregon2DecoderStepVarData: + // waiting for variable (sensor-specific data) + if(instance->decoder.decode_count_bit == instance->var_bits + OREGON2_CHECKSUM_BITS) { + instance->var_data = instance->decoder.decode_data & 0xFFFFFFFF; + + // reverse nibbles in var data + instance->var_data = (instance->var_data & 0x55555555) << 1 | + (instance->var_data & 0xAAAAAAAA) >> 1; + instance->var_data = (instance->var_data & 0x33333333) << 2 | + (instance->var_data & 0xCCCCCCCC) >> 2; + + instance->decoder.parser_step = Oregon2DecoderStepReset; + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + break; + } +} + +uint8_t subghz_protocol_decoder_oregon2_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderOregon2* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_oregon2_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzPresetDefinition* preset) { + furi_assert(context); + SubGhzProtocolDecoderOregon2* instance = context; + if(!subghz_block_generic_serialize(&instance->generic, flipper_format, preset)) return false; + uint32_t temp = instance->var_bits; + if(!flipper_format_write_uint32(flipper_format, "VarBits", &temp, 1)) { + FURI_LOG_E(TAG, "Error adding VarBits"); + return false; + } + if(!flipper_format_write_hex( + flipper_format, + "VarData", + (const uint8_t*)&instance->var_data, + sizeof(instance->var_data))) { + FURI_LOG_E(TAG, "Error adding VarData"); + return false; + } + return true; +} + +bool subghz_protocol_decoder_oregon2_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderOregon2* instance = context; + bool ret = false; + uint32_t temp_data; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(!flipper_format_read_uint32(flipper_format, "VarBits", &temp_data, 1)) { + FURI_LOG_E(TAG, "Missing VarLen"); + break; + } + instance->var_bits = (uint8_t)temp_data; + if(!flipper_format_read_hex( + flipper_format, + "VarData", + (uint8_t*)&instance->var_data, + sizeof(instance->var_data))) { + FURI_LOG_E(TAG, "Missing VarData"); + break; + } + if(instance->generic.data_count_bit != oregon2_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key: %d", instance->generic.data_count_bit); + break; + } + ret = true; + } while(false); + return ret; +} + +// append string of the variable data +static void + oregon2_var_data_append_string(uint16_t sensor_id, uint32_t var_data, string_t output) { + uint32_t val; + + if(sensor_id == 0xEC40) { + val = ((var_data >> 4) & 0xF) * 10 + ((var_data >> 8) & 0xF); + string_cat_printf( + output, + "Temp: %s%d.%d C\r\n", + (var_data & 0xF) ? "-" : "+", + val, + (uint32_t)(var_data >> 12) & 0xF); + } +} + +static void oregon2_append_check_sum(uint32_t fix_data, uint32_t var_data, string_t output) { + uint8_t sum = fix_data & 0xF; + uint8_t ref_sum = var_data & 0xFF; + var_data >>= 8; + + for(uint8_t i = 1; i < 8; i++) { + fix_data >>= 4; + var_data >>= 4; + sum += (fix_data & 0xF) + (var_data & 0xF); + } + + // swap calculated sum nibbles + sum = (((sum >> 4) & 0xF) | (sum << 4)) & 0xFF; + if(sum == ref_sum) + string_cat_printf(output, "Sum ok: 0x%hhX", ref_sum); + else + string_cat_printf(output, "Sum err: 0x%hhX vs 0x%hhX", ref_sum, sum); +} + +void subghz_protocol_decoder_oregon2_get_string(void* context, string_t output) { + furi_assert(context); + SubGhzProtocolDecoderOregon2* instance = context; + uint16_t sensor_id = OREGON2_SENSOR_ID(instance->generic.data); + string_cat_printf( + output, + "%s\r\n" + "ID: 0x%04lX, ch: %d%s, rc: 0x%02lX\r\n", + instance->generic.protocol_name, + (uint32_t)sensor_id, + (uint32_t)(instance->generic.data >> 12) & 0xF, + ((instance->generic.data & OREGON2_FLAG_BAT_LOW) ? ", low bat" : ""), + (uint32_t)(instance->generic.data >> 4) & 0xFF); + + if(instance->var_bits > 0) { + oregon2_var_data_append_string( + sensor_id, instance->var_data >> OREGON2_CHECKSUM_BITS, output); + oregon2_append_check_sum((uint32_t)instance->generic.data, instance->var_data, output); + } +} + +const SubGhzProtocolDecoder subghz_protocol_oregon2_decoder = { + .alloc = subghz_protocol_decoder_oregon2_alloc, + .free = subghz_protocol_decoder_oregon2_free, + + .feed = subghz_protocol_decoder_oregon2_feed, + .reset = subghz_protocol_decoder_oregon2_reset, + + .get_hash_data = subghz_protocol_decoder_oregon2_get_hash_data, + .serialize = subghz_protocol_decoder_oregon2_serialize, + .deserialize = subghz_protocol_decoder_oregon2_deserialize, + .get_string = subghz_protocol_decoder_oregon2_get_string, +}; + +const SubGhzProtocol subghz_protocol_oregon2 = { + .name = SUBGHZ_PROTOCOL_OREGON2_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, + + .decoder = &subghz_protocol_oregon2_decoder, +}; diff --git a/lib/subghz/protocols/oregon2.h b/lib/subghz/protocols/oregon2.h new file mode 100644 index 00000000..981b2599 --- /dev/null +++ b/lib/subghz/protocols/oregon2.h @@ -0,0 +1,5 @@ +#pragma once + +#include "base.h" +#define SUBGHZ_PROTOCOL_OREGON2_NAME "Oregon2" +extern const SubGhzProtocol subghz_protocol_oregon2; diff --git a/lib/subghz/protocols/phoenix_v2.c b/lib/subghz/protocols/phoenix_v2.c index 3d2796e4..d680b2e6 100644 --- a/lib/subghz/protocols/phoenix_v2.c +++ b/lib/subghz/protocols/phoenix_v2.c @@ -150,7 +150,7 @@ bool subghz_protocol_encoder_phoenix_v2_deserialize(void* context, FlipperFormat flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_phoenix_v2_get_upload(instance); + if(!subghz_protocol_encoder_phoenix_v2_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/princeton.c b/lib/subghz/protocols/princeton.c index 2ddfa2cb..a5b8134d 100644 --- a/lib/subghz/protocols/princeton.c +++ b/lib/subghz/protocols/princeton.c @@ -167,7 +167,7 @@ bool subghz_protocol_encoder_princeton_deserialize(void* context, FlipperFormat* flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - subghz_protocol_encoder_princeton_get_upload(instance); + if(!subghz_protocol_encoder_princeton_get_upload(instance)) break; instance->encoder.is_running = true; res = true; diff --git a/lib/subghz/protocols/raw.h b/lib/subghz/protocols/raw.h index 00654ad2..b52a7d84 100644 --- a/lib/subghz/protocols/raw.h +++ b/lib/subghz/protocols/raw.h @@ -4,6 +4,10 @@ #define SUBGHZ_PROTOCOL_RAW_NAME "RAW" +#ifdef __cplusplus +extern "C" { +#endif + typedef void (*SubGhzProtocolEncoderRAWCallbackEnd)(void* context); typedef struct SubGhzProtocolDecoderRAW SubGhzProtocolDecoderRAW; @@ -99,12 +103,6 @@ void subghz_protocol_encoder_raw_free(void* context); */ void subghz_protocol_encoder_raw_stop(void* context); -/** - * Сallback on completion of file transfer. - * @param context Pointer to a SubGhzProtocolEncoderRAW instance - */ -void subghz_protocol_raw_file_encoder_worker_callback_end(void* context); - /** * Set callback on completion of file transfer. * @param instance Pointer to a SubGhzProtocolEncoderRAW instance @@ -137,3 +135,7 @@ bool subghz_protocol_encoder_raw_deserialize(void* context, FlipperFormat* flipp * @return LevelDuration */ LevelDuration subghz_protocol_encoder_raw_yield(void* context); + +#ifdef __cplusplus +} +#endif diff --git a/lib/subghz/protocols/registry.c b/lib/subghz/protocols/registry.c index 8bb45e9a..453fa747 100644 --- a/lib/subghz/protocols/registry.c +++ b/lib/subghz/protocols/registry.c @@ -12,9 +12,7 @@ const SubGhzProtocol* subghz_protocol_registry[] = { &subghz_protocol_chamb_code, &subghz_protocol_power_smart, &subghz_protocol_marantec, &subghz_protocol_bett, &subghz_protocol_doitrand, &subghz_protocol_phoenix_v2, &subghz_protocol_honeywell_wdb, &subghz_protocol_magellen, &subghz_protocol_intertechno_v3, - &subghz_protocol_clemsa - -}; + &subghz_protocol_clemsa, &subghz_protocol_oregon2}; const SubGhzProtocol* subghz_protocol_registry_get_by_name(const char* name) { for(size_t i = 0; i < subghz_protocol_registry_count(); i++) { diff --git a/lib/subghz/protocols/registry.h b/lib/subghz/protocols/registry.h index ad115102..8eb464ad 100644 --- a/lib/subghz/protocols/registry.h +++ b/lib/subghz/protocols/registry.h @@ -36,6 +36,7 @@ #include "magellen.h" #include "intertechno_v3.h" #include "clemsa.h" +#include "oregon2.h" /** * Registration by name SubGhzProtocol. diff --git a/lib/subghz/receiver.h b/lib/subghz/receiver.h index 1357ecbe..2ef722d1 100644 --- a/lib/subghz/receiver.h +++ b/lib/subghz/receiver.h @@ -3,6 +3,10 @@ #include "types.h" #include "protocols/base.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct SubGhzReceiver SubGhzReceiver; typedef void (*SubGhzReceiverCallback)( @@ -63,3 +67,7 @@ void subghz_receiver_set_filter(SubGhzReceiver* instance, SubGhzProtocolFlag fil */ SubGhzProtocolDecoderBase* subghz_receiver_search_decoder_base_by_name(SubGhzReceiver* instance, const char* decoder_name); + +#ifdef __cplusplus +} +#endif diff --git a/lib/subghz/subghz_keystore.c b/lib/subghz/subghz_keystore.c index 0abd2d5e..4d2eb0e5 100644 --- a/lib/subghz/subghz_keystore.c +++ b/lib/subghz/subghz_keystore.c @@ -114,62 +114,69 @@ static bool subghz_keystore_read_file(SubGhzKeystore* instance, Stream* stream, char* encrypted_line = malloc(SUBGHZ_KEYSTORE_FILE_ENCRYPTED_LINE_SIZE); size_t encrypted_line_cursor = 0; - if(iv) furi_hal_crypto_store_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv); - - size_t ret = 0; do { - ret = stream_read(stream, buffer, FILE_BUFFER_SIZE); - for(uint16_t i = 0; i < ret; i++) { - if(buffer[i] == '\n' && encrypted_line_cursor > 0) { - // Process line - if(iv) { - // Data alignment check, 32 instead of 16 because of hex encoding - size_t len = strlen(encrypted_line); - if(len % 32 == 0) { - // Inplace hex to bin conversion - for(size_t i = 0; i < len; i += 2) { - uint8_t hi_nibble = 0; - uint8_t lo_nibble = 0; - hex_char_to_hex_nibble(encrypted_line[i], &hi_nibble); - hex_char_to_hex_nibble(encrypted_line[i + 1], &lo_nibble); - encrypted_line[i / 2] = (hi_nibble << 4) | lo_nibble; - } - len /= 2; - - if(furi_hal_crypto_decrypt( - (uint8_t*)encrypted_line, (uint8_t*)decrypted_line, len)) { - subghz_keystore_process_line(instance, decrypted_line); - } else { - FURI_LOG_E(TAG, "Decryption failed"); - result = false; - break; - } - } else { - FURI_LOG_E(TAG, "Invalid encrypted data: %s", encrypted_line); - } - } else { - subghz_keystore_process_line(instance, encrypted_line); - } - // reset line buffer - memset(decrypted_line, 0, SUBGHZ_KEYSTORE_FILE_DECRYPTED_LINE_SIZE); - memset(encrypted_line, 0, SUBGHZ_KEYSTORE_FILE_ENCRYPTED_LINE_SIZE); - encrypted_line_cursor = 0; - } else if(buffer[i] == '\r' || buffer[i] == '\n') { - // do not add line endings to the buffer - } else { - if(encrypted_line_cursor < SUBGHZ_KEYSTORE_FILE_ENCRYPTED_LINE_SIZE) { - encrypted_line[encrypted_line_cursor] = buffer[i]; - encrypted_line_cursor++; - } else { - FURI_LOG_E(TAG, "Malformed file"); - result = false; - break; - } + if(iv) { + if(!furi_hal_crypto_store_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv)) { + FURI_LOG_E(TAG, "Unable to load decryption key"); + break; } } - } while(ret > 0 && result); - if(iv) furi_hal_crypto_store_unload_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT); + size_t ret = 0; + do { + ret = stream_read(stream, buffer, FILE_BUFFER_SIZE); + for(uint16_t i = 0; i < ret; i++) { + if(buffer[i] == '\n' && encrypted_line_cursor > 0) { + // Process line + if(iv) { + // Data alignment check, 32 instead of 16 because of hex encoding + size_t len = strlen(encrypted_line); + if(len % 32 == 0) { + // Inplace hex to bin conversion + for(size_t i = 0; i < len; i += 2) { + uint8_t hi_nibble = 0; + uint8_t lo_nibble = 0; + hex_char_to_hex_nibble(encrypted_line[i], &hi_nibble); + hex_char_to_hex_nibble(encrypted_line[i + 1], &lo_nibble); + encrypted_line[i / 2] = (hi_nibble << 4) | lo_nibble; + } + len /= 2; + + if(furi_hal_crypto_decrypt( + (uint8_t*)encrypted_line, (uint8_t*)decrypted_line, len)) { + subghz_keystore_process_line(instance, decrypted_line); + } else { + FURI_LOG_E(TAG, "Decryption failed"); + result = false; + break; + } + } else { + FURI_LOG_E(TAG, "Invalid encrypted data: %s", encrypted_line); + } + } else { + subghz_keystore_process_line(instance, encrypted_line); + } + // reset line buffer + memset(decrypted_line, 0, SUBGHZ_KEYSTORE_FILE_DECRYPTED_LINE_SIZE); + memset(encrypted_line, 0, SUBGHZ_KEYSTORE_FILE_ENCRYPTED_LINE_SIZE); + encrypted_line_cursor = 0; + } else if(buffer[i] == '\r' || buffer[i] == '\n') { + // do not add line endings to the buffer + } else { + if(encrypted_line_cursor < SUBGHZ_KEYSTORE_FILE_ENCRYPTED_LINE_SIZE) { + encrypted_line[encrypted_line_cursor] = buffer[i]; + encrypted_line_cursor++; + } else { + FURI_LOG_E(TAG, "Malformed file"); + result = false; + break; + } + } + } + } while(ret > 0 && result); + + if(iv) furi_hal_crypto_store_unload_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT); + } while(false); free(encrypted_line); free(decrypted_line); diff --git a/lib/subghz/subghz_keystore.h b/lib/subghz/subghz_keystore.h index be9a19df..2b7880f0 100644 --- a/lib/subghz/subghz_keystore.h +++ b/lib/subghz/subghz_keystore.h @@ -4,6 +4,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { string_t name; uint64_t key; @@ -70,3 +74,7 @@ bool subghz_keystore_raw_encrypted_save( * @return true On success */ bool subghz_keystore_raw_get_data(const char* file_name, size_t offset, uint8_t* data, size_t len); + +#ifdef __cplusplus +} +#endif diff --git a/lib/subghz/subghz_tx_rx_worker.h b/lib/subghz/subghz_tx_rx_worker.h index 3f3f8276..ddc02e74 100644 --- a/lib/subghz/subghz_tx_rx_worker.h +++ b/lib/subghz/subghz_tx_rx_worker.h @@ -2,6 +2,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + typedef void (*SubGhzTxRxWorkerCallbackHaveRead)(void* context); typedef struct SubGhzTxRxWorker SubGhzTxRxWorker; @@ -79,3 +83,7 @@ void subghz_tx_rx_worker_stop(SubGhzTxRxWorker* instance); * @return bool - true if running */ bool subghz_tx_rx_worker_is_running(SubGhzTxRxWorker* instance); + +#ifdef __cplusplus +} +#endif diff --git a/lib/subghz/subghz_worker.h b/lib/subghz/subghz_worker.h index bb303165..f85b1fdc 100644 --- a/lib/subghz/subghz_worker.h +++ b/lib/subghz/subghz_worker.h @@ -2,6 +2,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct SubGhzWorker SubGhzWorker; typedef void (*SubGhzWorkerOverrunCallback)(void* context); @@ -62,3 +66,7 @@ void subghz_worker_stop(SubGhzWorker* instance); * @return bool - true if running */ bool subghz_worker_is_running(SubGhzWorker* instance); + +#ifdef __cplusplus +} +#endif diff --git a/lib/subghz/transmitter.h b/lib/subghz/transmitter.h index 53f10b07..cce98a46 100644 --- a/lib/subghz/transmitter.h +++ b/lib/subghz/transmitter.h @@ -4,6 +4,10 @@ #include "environment.h" #include "protocols/base.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct SubGhzTransmitter SubGhzTransmitter; /** @@ -45,3 +49,7 @@ bool subghz_transmitter_deserialize(SubGhzTransmitter* instance, FlipperFormat* * @return LevelDuration */ LevelDuration subghz_transmitter_yield(void* context); + +#ifdef __cplusplus +} +#endif diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index e4f2cbd0..d631431e 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -7,6 +7,25 @@ env.Append( CPPPATH=[ "#/lib/toolbox", ], + SDK_HEADERS=[ + File("#/lib/toolbox/manchester_decoder.h"), + File("#/lib/toolbox/manchester_encoder.h"), + File("#/lib/toolbox/path.h"), + File("#/lib/toolbox/random_name.h"), + File("#/lib/toolbox/hmac_sha256.h"), + File("#/lib/toolbox/crc32_calc.h"), + File("#/lib/toolbox/dir_walk.h"), + File("#/lib/toolbox/md5.h"), + File("#/lib/toolbox/args.h"), + File("#/lib/toolbox/saved_struct.h"), + File("#/lib/toolbox/version.h"), + File("#/lib/toolbox/tar/tar_archive.h"), + File("#/lib/toolbox/stream/stream.h"), + File("#/lib/toolbox/stream/file_stream.h"), + File("#/lib/toolbox/stream/string_stream.h"), + File("#/lib/toolbox/stream/buffered_file_stream.h"), + File("#/lib/toolbox/protocols/protocol_dict.h"), + ], ) diff --git a/lib/toolbox/hmac_sha256.h b/lib/toolbox/hmac_sha256.h index 01fc0b14..add12314 100644 --- a/lib/toolbox/hmac_sha256.h +++ b/lib/toolbox/hmac_sha256.h @@ -1,3 +1,10 @@ +#pragma once + +#include "sha256.h" + +#ifdef __cplusplus +extern "C" { +#endif typedef struct hmac_context { void (*init_hash)(const struct hmac_context* context); @@ -25,3 +32,7 @@ void hmac_sha256_update( unsigned message_size); void hmac_sha256_finish(const hmac_sha256_context* ctx, const uint8_t* K, uint8_t* hash_result); + +#ifdef __cplusplus +} +#endif diff --git a/lib/toolbox/saved_struct.h b/lib/toolbox/saved_struct.h index aae41bd6..aaa04eef 100644 --- a/lib/toolbox/saved_struct.h +++ b/lib/toolbox/saved_struct.h @@ -4,6 +4,14 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + bool saved_struct_load(const char* path, void* data, size_t size, uint8_t magic, uint8_t version); bool saved_struct_save(const char* path, void* data, size_t size, uint8_t magic, uint8_t version); + +#ifdef __cplusplus +} +#endif diff --git a/lib/toolbox/sha256.h b/lib/toolbox/sha256.h index 85b9709d..c544d3eb 100644 --- a/lib/toolbox/sha256.h +++ b/lib/toolbox/sha256.h @@ -1,3 +1,9 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + #define SHA256_DIGEST_SIZE 32 #define SHA256_BLOCK_SIZE 64 @@ -12,3 +18,7 @@ void sha256_start(sha256_context* ctx); void sha256_finish(sha256_context* ctx, unsigned char output[32]); void sha256_update(sha256_context* ctx, const unsigned char* input, unsigned int ilen); void sha256_process(sha256_context* ctx); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/toolbox/tar/tar_archive.c b/lib/toolbox/tar/tar_archive.c index 5ac89a0f..0d42d162 100644 --- a/lib/toolbox/tar/tar_archive.c +++ b/lib/toolbox/tar/tar_archive.c @@ -294,6 +294,7 @@ bool tar_archive_add_file( break; } + success = true; // if file is empty, that's not an error uint16_t bytes_read = 0; while((bytes_read = storage_file_read(src_file, file_buffer, FILE_BLOCK_SIZE))) { success = tar_archive_file_add_data_block(archive, file_buffer, bytes_read); diff --git a/lib/u8g2/u8g2_glue.c b/lib/u8g2/u8g2_glue.c index 77f37f14..17a702b5 100644 --- a/lib/u8g2/u8g2_glue.c +++ b/lib/u8g2/u8g2_glue.c @@ -225,7 +225,7 @@ uint8_t u8x8_d_st756x_flipper(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* * RR = 10 / ((1 - (63 - 32) / 162) * 2.1) ~= 5.88 is 6 (0b110) * Bias = 1/9 (false) */ - u8x8_d_st756x_init(u8x8, 32, 0b110, false); + u8x8_d_st756x_init(u8x8, 31, 0b110, false); } else { /* ERC v1(ST7565) and v2(ST7567) * EV = 33 @@ -233,7 +233,7 @@ uint8_t u8x8_d_st756x_flipper(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* * RR = 9.3 / ((1 - (63 - 32) / 162) * 2.1) ~= 5.47 is 5.5 (0b101) * Bias = 1/9 (false) */ - u8x8_d_st756x_init(u8x8, 33, 0b101, false); + u8x8_d_st756x_init(u8x8, 32, 0b101, false); } break; case U8X8_MSG_DISPLAY_SET_FLIP_MODE: diff --git a/lib/update_util/lfs_backup.c b/lib/update_util/lfs_backup.c index 724da365..089f032d 100644 --- a/lib/update_util/lfs_backup.c +++ b/lib/update_util/lfs_backup.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #define LFS_BACKUP_DEFAULT_LOCATION EXT_PATH(LFS_BACKUP_DEFAULT_FILENAME) @@ -42,8 +42,7 @@ bool lfs_backup_create(Storage* storage, const char* destination) { bool lfs_backup_exists(Storage* storage, const char* source) { const char* final_source = source && strlen(source) ? source : LFS_BACKUP_DEFAULT_LOCATION; - FileInfo fi; - return storage_common_stat(storage, final_source, &fi) == FSE_OK; + return storage_common_stat(storage, final_source, NULL) == FSE_OK; } bool lfs_backup_unpack(Storage* storage, const char* source) { diff --git a/lib/update_util/update_operation.c b/lib/update_util/update_operation.c index 138828ff..56f412a9 100644 --- a/lib/update_util/update_operation.c +++ b/lib/update_util/update_operation.c @@ -12,7 +12,7 @@ #define UPDATE_ROOT_DIR EXT_PATH("update") /* Need at least 4 free LFS pages before update */ -#define UPDATE_MIN_INT_FREE_SPACE 4 * 4 * 1024 +#define UPDATE_MIN_INT_FREE_SPACE 2 * 4 * 1024 static const char* update_prepare_result_descr[] = { [UpdatePrepareResultOK] = "OK", diff --git a/scripts/assets.py b/scripts/assets.py index b27b29ef..1f36a135 100755 --- a/scripts/assets.py +++ b/scripts/assets.py @@ -3,16 +3,12 @@ from flipper.app import App from flipper.assets.icon import file2image -import logging -import argparse -import subprocess -import io import os -import sys ICONS_SUPPORTED_FORMATS = ["png"] ICONS_TEMPLATE_H_HEADER = """#pragma once + #include """ diff --git a/scripts/runfap.py b/scripts/runfap.py new file mode 100644 index 00000000..c2c0f78d --- /dev/null +++ b/scripts/runfap.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 + +import posixpath +from typing import final +from flipper.app import App +from flipper.storage import FlipperStorage +from flipper.utils.cdc import resolve_port + +import logging +import os +import pathlib +import serial.tools.list_ports as list_ports + + +class Main(App): + def init(self): + self.parser.add_argument("-p", "--port", help="CDC Port", default="auto") + + self.parser.add_argument("fap_src_path", help="App file to upload") + self.parser.add_argument( + "--fap_dst_dir", help="Upload path", default="/ext/apps", required=False + ) + self.parser.set_defaults(func=self.install) + + # logging + self.logger = logging.getLogger() + + # make directory with exist check + def mkdir_on_storage(self, storage, flipper_dir_path): + if not storage.exist_dir(flipper_dir_path): + self.logger.debug(f'"{flipper_dir_path}" does not exist, creating') + if not storage.mkdir(flipper_dir_path): + self.logger.error(f"Error: {storage.last_error}") + return False + else: + self.logger.debug(f'"{flipper_dir_path}" already exists') + return True + + # send file with exist check and hash check + def send_file_to_storage(self, storage, flipper_file_path, local_file_path, force): + exists = storage.exist_file(flipper_file_path) + do_upload = not exists + if exists: + hash_local = storage.hash_local(local_file_path) + hash_flipper = storage.hash_flipper(flipper_file_path) + self.logger.debug(f"hash check: local {hash_local}, flipper {hash_flipper}") + do_upload = force or (hash_local != hash_flipper) + + if do_upload: + self.logger.info(f'Sending "{local_file_path}" to "{flipper_file_path}"') + if not storage.send_file(local_file_path, flipper_file_path): + self.logger.error(f"Error: {storage.last_error}") + return False + return True + + def install(self): + if not (port := resolve_port(self.logger, self.args.port)): + return 1 + + storage = FlipperStorage(port) + storage.start() + + try: + fap_local_path = self.args.fap_src_path + self.args.fap_dst_dir = self.args.fap_dst_dir.rstrip("/\\") + + if not os.path.isfile(fap_local_path): + self.logger.error(f"Error: source .fap ({fap_local_path}) not found") + return -1 + + fap_dst_path = posixpath.join( + self.args.fap_dst_dir, os.path.basename(fap_local_path) + ) + + self.logger.info(f'Installing "{fap_local_path}" to {fap_dst_path}') + + if not self.mkdir_on_storage(storage, self.args.fap_dst_dir): + self.logger.error(f"Error: cannot create dir: {storage.last_error}") + return -2 + + if not self.send_file_to_storage( + storage, fap_dst_path, fap_local_path, False + ): + self.logger.error(f"Error: upload failed: {storage.last_error}") + return -3 + + storage.send_and_wait_eol(f'loader open "Applications" {fap_dst_path}\r') + result = storage.read.until(storage.CLI_EOL) + if len(result): + self.logger.error(f"Unexpected response: {result.decode('ascii')}") + return -4 + + return 0 + finally: + storage.stop() + + +if __name__ == "__main__": + Main()() diff --git a/scripts/toolchain/fbtenv.cmd b/scripts/toolchain/fbtenv.cmd index cf5d2441..1403837d 100644 --- a/scripts/toolchain/fbtenv.cmd +++ b/scripts/toolchain/fbtenv.cmd @@ -13,7 +13,7 @@ if not [%FBT_NOENV%] == [] ( exit /b 0 ) -set "FLIPPER_TOOLCHAIN_VERSION=12" +set "FLIPPER_TOOLCHAIN_VERSION=15" set "FBT_TOOLCHAIN_ROOT=%FBT_ROOT%\toolchain\i686-windows" diff --git a/scripts/toolchain/fbtenv.sh b/scripts/toolchain/fbtenv.sh index da03df22..f68e4c0b 100755 --- a/scripts/toolchain/fbtenv.sh +++ b/scripts/toolchain/fbtenv.sh @@ -5,7 +5,7 @@ # public variables DEFAULT_SCRIPT_PATH="$(pwd -P)"; SCRIPT_PATH="${SCRIPT_PATH:-$DEFAULT_SCRIPT_PATH}"; -FBT_TOOLCHAIN_VERSION="${FBT_TOOLCHAIN_VERSION:-"12"}"; +FBT_TOOLCHAIN_VERSION="${FBT_TOOLCHAIN_VERSION:-"15"}"; FBT_TOOLCHAIN_PATH="${FBT_TOOLCHAIN_PATH:-$SCRIPT_PATH}"; fbtenv_show_usage() diff --git a/site_scons/cc.scons b/site_scons/cc.scons index e71db2ba..c923b387 100644 --- a/site_scons/cc.scons +++ b/site_scons/cc.scons @@ -11,6 +11,7 @@ ENV.AppendUnique( "-fno-use-cxa-atexit", "-fno-exceptions", "-fno-threadsafe-statics", + "-ftemplate-depth=4096", ], CCFLAGS=[ "-mcpu=cortex-m4", diff --git a/site_scons/commandline.scons b/site_scons/commandline.scons index 4c96268b..2eeda247 100644 --- a/site_scons/commandline.scons +++ b/site_scons/commandline.scons @@ -68,6 +68,11 @@ vars.AddVariables( "7", ], ), + BoolVariable( + "DEBUG_TOOLS", + help="Enable debug tools to be built", + default=False, + ), ) vars.Add( @@ -186,21 +191,17 @@ vars.Add( help="Map of (configuration_name->application_list)", default={ "default": ( - "crypto_start", # Svc "basic_services", # Apps - "basic_apps", - "updater_app", - "archive", + "main_apps", + "system_apps", # Settings - "passport", - "system_settings", - "about", + "settings_apps", # Plugins - "basic_plugins", + # "basic_plugins", # Debug - "debug_apps", + # "debug_apps", ) }, ) @@ -211,4 +212,26 @@ vars.Add( default="default", ) +vars.Add( + "APPSRC", + help="Application source directory for app to build & upload", + default="", +) + +# List of tuples (directory, add_to_global_include_path) +vars.Add( + "APPDIRS", + help="Directories to search for firmware components & external apps", + default=[ + ("applications", False), + ("applications/services", True), + ("applications/main", True), + ("applications/settings", False), + ("applications/system", False), + ("applications/debug", False), + ("applications/plugins", False), + ("applications_user", False), + ], +) + Return("vars") diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons new file mode 100644 index 00000000..4cb5e35c --- /dev/null +++ b/site_scons/extapps.scons @@ -0,0 +1,97 @@ +Import("ENV") + + +from fbt.appmanifest import FlipperAppType + +appenv = ENV.Clone( + tools=[("fbt_extapps", {"EXT_APPS_WORK_DIR": ENV.subst("${BUILD_DIR}/.extapps")})] +) + +appenv.Replace( + LINKER_SCRIPT="application-ext", +) + +appenv.AppendUnique( + CCFLAGS=[ + "-ggdb3", + "-mword-relocations", + "-mlong-calls", + "-fno-common", + "-nostdlib", + "-fvisibility=hidden", + ], + LINKFLAGS=[ + "-Ur", + "-Wl,-Ur", + # "-Wl,--orphan-handling=error", + "-Bsymbolic", + "-nostartfiles", + "-mlong-calls", + "-fno-common", + "-nostdlib", + "-Wl,--gc-sections", + "-Wl,--no-export-dynamic", + "-fvisibility=hidden", + "-Wl,-e${APP_ENTRY}", + "-Xlinker", + "-Map=${TARGET}.map", + "-specs=nano.specs", + "-specs=nosys.specs", + ], + LIBS=[ + "m", + "gcc", + "stdc++", + "supc++", + ], +) + + +extapps = appenv["_extapps"] = { + "compact": {}, + "debug": {}, + "validators": {}, + "dist": {}, +} + + +def build_app_as_external(env, appdef): + compact_elf, debug_elf, validator = env.BuildAppElf(appdef) + extapps["compact"][appdef.appid] = compact_elf + extapps["debug"][appdef.appid] = debug_elf + extapps["validators"][appdef.appid] = validator + extapps["dist"][appdef.appid] = (appdef.fap_category, compact_elf) + + +apps_to_build_as_faps = [ + FlipperAppType.PLUGIN, + FlipperAppType.EXTERNAL, +] +if appenv["DEBUG_TOOLS"]: + apps_to_build_as_faps.append(FlipperAppType.DEBUG) + +for apptype in apps_to_build_as_faps: + for app in appenv["APPBUILD"].get_apps_of_type(apptype, True): + build_app_as_external(appenv, app) + +# Ugly access to global option +if extra_app_list := GetOption("extra_ext_apps"): + for extra_app in extra_app_list.split(","): + build_app_as_external(appenv, appenv["APPMGR"].get(extra_app)) + + +if appenv["FORCE"]: + appenv.AlwaysBuild(extapps["compact"].values()) + +Alias(appenv["FIRMWARE_BUILD_CFG"] + "_extapps", extapps["compact"].values()) + +if appsrc := appenv.subst("$APPSRC"): + app_manifest, fap_file = appenv.GetExtAppFromPath(appsrc) + appenv.PhonyTarget( + "launch_app", + '${PYTHON3} scripts/runfap.py ${SOURCE} --fap_dst_dir "/ext/apps/${FAP_CATEGORY}"', + source=fap_file, + FAP_CATEGORY=app_manifest.fap_category, + ) + +Return("extapps") diff --git a/site_scons/fbt/appmanifest.py b/site_scons/fbt/appmanifest.py index aacf248e..a0ab5e7c 100644 --- a/site_scons/fbt/appmanifest.py +++ b/site_scons/fbt/appmanifest.py @@ -1,5 +1,5 @@ from dataclasses import dataclass, field -from typing import List, Optional +from typing import List, Optional, Tuple from enum import Enum import os @@ -25,7 +25,7 @@ class FlipperAppType(Enum): class FlipperApplication: appid: str apptype: FlipperAppType - name: Optional[str] = None + name: Optional[str] = "" entry_point: Optional[str] = None flags: List[str] = field(default_factory=lambda: ["Default"]) cdefines: List[str] = field(default_factory=list) @@ -35,7 +35,19 @@ class FlipperApplication: stack_size: int = 2048 icon: Optional[str] = None order: int = 0 - _appdir: Optional[str] = None + sdk_headers: List[str] = field(default_factory=list) + # .fap-specific + sources: List[str] = field(default_factory=lambda: ["*.c*"]) + fap_version: Tuple[int] = field(default_factory=lambda: (0, 0)) + fap_icon: Optional[str] = None + fap_libs: List[str] = field(default_factory=list) + fap_category: str = "" + fap_description: str = "" + fap_author: str = "" + fap_weburl: str = "" + # Internally used by fbt + _appdir: Optional[object] = None + _apppath: Optional[str] = None class AppManager: @@ -50,7 +62,13 @@ class AppManager: f"Missing application manifest for '{appname}'" ) - def load_manifest(self, app_manifest_path: str, app_dir_name: str): + def find_by_appdir(self, appdir: str): + for app in self.known_apps.values(): + if app._appdir.name == appdir: + return app + return None + + def load_manifest(self, app_manifest_path: str, app_dir_node: object): if not os.path.exists(app_manifest_path): raise FlipperManifestException( f"App manifest not found at path {app_manifest_path}" @@ -61,7 +79,14 @@ class AppManager: def App(*args, **kw): nonlocal app_manifests - app_manifests.append(FlipperApplication(*args, **kw, _appdir=app_dir_name)) + app_manifests.append( + FlipperApplication( + *args, + **kw, + _appdir=app_dir_node, + _apppath=os.path.dirname(app_manifest_path), + ), + ) try: with open(app_manifest_path, "rt") as manifest_file: @@ -172,19 +197,32 @@ class AppBuildset: cdefs.update(app.cdefines) return sorted(list(cdefs)) - def get_apps_of_type(self, apptype: FlipperAppType): + def get_sdk_headers(self): + sdk_headers = [] + for app in self.apps: + sdk_headers.extend([app._appdir.File(header) for header in app.sdk_headers]) + return sdk_headers + + def get_apps_of_type(self, apptype: FlipperAppType, all_known: bool = False): return sorted( - filter(lambda app: app.apptype == apptype, self.apps), + filter( + lambda app: app.apptype == apptype, + self.appmgr.known_apps.values() if all_known else self.apps, + ), key=lambda app: app.order, ) + def get_builtin_apps(self): + return list( + filter(lambda app: app.apptype in self.BUILTIN_APP_TYPES, self.apps) + ) + def get_builtin_app_folders(self): return sorted( set( - app._appdir - for app in filter( - lambda app: app.apptype in self.BUILTIN_APP_TYPES, self.apps - ) + (app._appdir, source_type) + for app in self.get_builtin_apps() + for source_type in app.sources ) ) diff --git a/site_scons/fbt/elfmanifest.py b/site_scons/fbt/elfmanifest.py new file mode 100644 index 00000000..313a64c0 --- /dev/null +++ b/site_scons/fbt/elfmanifest.py @@ -0,0 +1,85 @@ +from dataclasses import dataclass +import os + +import struct +from dataclasses import dataclass, field + +from .appmanifest import FlipperApplication + + +_MANIFEST_MAGIC = 0x52474448 + + +@dataclass +class ElfManifestBaseHeader: + manifest_version: int + api_version: int + hardware_target_id: int + + manifest_magic: int = 0x52474448 + + def as_bytes(self): + return struct.pack( + " 32: + raise ValueError( + f"Flipper app icon must be 32 bytes or less, but {len(image.data)} bytes were given" + ) + image_data = image.data + + app_version_as_int = ((app_manifest.fap_version[0] & 0xFFFF) << 16) | ( + app_manifest.fap_version[1] & 0xFFFF + ) + + data = ElfManifestBaseHeader( + manifest_version=1, + api_version=sdk_version, + hardware_target_id=hardware_target, + ).as_bytes() + data += ElfManifestV1( + stack_size=app_manifest.stack_size, + app_version=app_version_as_int, + name=app_manifest.name, + icon=image_data, + ).as_bytes() + + return data diff --git a/site_scons/fbt/sdk.py b/site_scons/fbt/sdk.py new file mode 100644 index 00000000..3d4a17b2 --- /dev/null +++ b/site_scons/fbt/sdk.py @@ -0,0 +1,519 @@ +import operator +import os +import csv +import operator + +from enum import Enum, auto +from typing import List, Set, ClassVar, Any +from dataclasses import dataclass, field + +from cxxheaderparser.parser import CxxParser + + +# 'Fixing' complaints about typedefs +CxxParser._fundamentals.discard("wchar_t") + +from cxxheaderparser.types import ( + EnumDecl, + Field, + ForwardDecl, + FriendDecl, + Function, + Method, + Typedef, + UsingAlias, + UsingDecl, + Variable, + Pointer, + Type, + PQName, + NameSpecifier, + FundamentalSpecifier, + Parameter, + Array, + Value, + Token, + FunctionType, +) + +from cxxheaderparser.parserstate import ( + State, + EmptyBlockState, + ClassBlockState, + ExternBlockState, + NamespaceBlockState, +) + + +@dataclass(frozen=True) +class ApiEntryFunction: + name: str + returns: str + params: str + + csv_type: ClassVar[str] = "Function" + + def dictify(self): + return dict(name=self.name, type=self.returns, params=self.params) + + +@dataclass(frozen=True) +class ApiEntryVariable: + name: str + var_type: str + + csv_type: ClassVar[str] = "Variable" + + def dictify(self): + return dict(name=self.name, type=self.var_type, params=None) + + +@dataclass(frozen=True) +class ApiHeader: + name: str + + csv_type: ClassVar[str] = "Header" + + def dictify(self): + return dict(name=self.name, type=None, params=None) + + +@dataclass +class ApiEntries: + # These are sets, to avoid creating duplicates when we have multiple + # declarations with same signature + functions: Set[ApiEntryFunction] = field(default_factory=set) + variables: Set[ApiEntryVariable] = field(default_factory=set) + headers: Set[ApiHeader] = field(default_factory=set) + + +class SymbolManager: + def __init__(self): + self.api = ApiEntries() + self.name_hashes = set() + + # Calculate hash of name and raise exception if it already is in the set + def _name_check(self, name: str): + name_hash = gnu_sym_hash(name) + if name_hash in self.name_hashes: + raise Exception(f"Hash collision on {name}") + self.name_hashes.add(name_hash) + + def add_function(self, function_def: ApiEntryFunction): + if function_def in self.api.functions: + return + self._name_check(function_def.name) + self.api.functions.add(function_def) + + def add_variable(self, variable_def: ApiEntryVariable): + if variable_def in self.api.variables: + return + self._name_check(variable_def.name) + self.api.variables.add(variable_def) + + def add_header(self, header: str): + self.api.headers.add(ApiHeader(header)) + + +def gnu_sym_hash(name: str): + h = 0x1505 + for c in name: + h = (h << 5) + h + ord(c) + return str(hex(h))[-8:] + + +class SdkCollector: + def __init__(self): + self.symbol_manager = SymbolManager() + + def add_header_to_sdk(self, header: str): + self.symbol_manager.add_header(header) + + def process_source_file_for_sdk(self, file_path: str): + visitor = SdkCxxVisitor(self.symbol_manager) + with open(file_path, "rt") as f: + content = f.read() + parser = CxxParser(file_path, content, visitor, None) + parser.parse() + + def get_api(self): + return self.symbol_manager.api + + +def stringify_array_dimension(size_descr): + if not size_descr: + return "" + return stringify_descr(size_descr) + + +def stringify_array_descr(type_descr): + assert isinstance(type_descr, Array) + return ( + stringify_descr(type_descr.array_of), + stringify_array_dimension(type_descr.size), + ) + + +def stringify_descr(type_descr): + if isinstance(type_descr, (NameSpecifier, FundamentalSpecifier)): + return type_descr.name + elif isinstance(type_descr, PQName): + return "::".join(map(stringify_descr, type_descr.segments)) + elif isinstance(type_descr, Pointer): + # Hack + if isinstance(type_descr.ptr_to, FunctionType): + return stringify_descr(type_descr.ptr_to) + return f"{stringify_descr(type_descr.ptr_to)}*" + elif isinstance(type_descr, Type): + return ( + f"{'const ' if type_descr.const else ''}" + f"{'volatile ' if type_descr.volatile else ''}" + f"{stringify_descr(type_descr.typename)}" + ) + elif isinstance(type_descr, Parameter): + return stringify_descr(type_descr.type) + elif isinstance(type_descr, Array): + # Hack for 2d arrays + if isinstance(type_descr.array_of, Array): + argtype, dimension = stringify_array_descr(type_descr.array_of) + return ( + f"{argtype}[{stringify_array_dimension(type_descr.size)}][{dimension}]" + ) + return f"{stringify_descr(type_descr.array_of)}[{stringify_array_dimension(type_descr.size)}]" + elif isinstance(type_descr, Value): + return " ".join(map(stringify_descr, type_descr.tokens)) + elif isinstance(type_descr, FunctionType): + return f"{stringify_descr(type_descr.return_type)} (*)({', '.join(map(stringify_descr, type_descr.parameters))})" + elif isinstance(type_descr, Token): + return type_descr.value + elif type_descr is None: + return "" + else: + raise Exception("unsupported type_descr: %s" % type_descr) + + +class SdkCxxVisitor: + def __init__(self, symbol_manager: SymbolManager): + self.api = symbol_manager + + def on_variable(self, state: State, v: Variable) -> None: + if not v.extern: + return + + self.api.add_variable( + ApiEntryVariable( + stringify_descr(v.name), + stringify_descr(v.type), + ) + ) + + def on_function(self, state: State, fn: Function) -> None: + if fn.inline or fn.has_body: + return + + self.api.add_function( + ApiEntryFunction( + stringify_descr(fn.name), + stringify_descr(fn.return_type), + ", ".join(map(stringify_descr, fn.parameters)) + + (", ..." if fn.vararg else ""), + ) + ) + + def on_define(self, state: State, content: str) -> None: + pass + + def on_pragma(self, state: State, content: str) -> None: + pass + + def on_include(self, state: State, filename: str) -> None: + pass + + def on_empty_block_start(self, state: EmptyBlockState) -> None: + pass + + def on_empty_block_end(self, state: EmptyBlockState) -> None: + pass + + def on_extern_block_start(self, state: ExternBlockState) -> None: + pass + + def on_extern_block_end(self, state: ExternBlockState) -> None: + pass + + def on_namespace_start(self, state: NamespaceBlockState) -> None: + pass + + def on_namespace_end(self, state: NamespaceBlockState) -> None: + pass + + def on_forward_decl(self, state: State, fdecl: ForwardDecl) -> None: + pass + + def on_typedef(self, state: State, typedef: Typedef) -> None: + pass + + def on_using_namespace(self, state: State, namespace: List[str]) -> None: + pass + + def on_using_alias(self, state: State, using: UsingAlias) -> None: + pass + + def on_using_declaration(self, state: State, using: UsingDecl) -> None: + pass + + def on_enum(self, state: State, enum: EnumDecl) -> None: + pass + + def on_class_start(self, state: ClassBlockState) -> None: + pass + + def on_class_field(self, state: State, f: Field) -> None: + pass + + def on_class_method(self, state: ClassBlockState, method: Method) -> None: + pass + + def on_class_friend(self, state: ClassBlockState, friend: FriendDecl) -> None: + pass + + def on_class_end(self, state: ClassBlockState) -> None: + pass + + +@dataclass(frozen=True) +class SdkVersion: + major: int = 0 + minor: int = 0 + + csv_type: ClassVar[str] = "Version" + + def __str__(self) -> str: + return f"{self.major}.{self.minor}" + + def as_int(self) -> int: + return ((self.major & 0xFFFF) << 16) | (self.minor & 0xFFFF) + + @staticmethod + def from_str(s: str) -> "SdkVersion": + major, minor = s.split(".") + return SdkVersion(int(major), int(minor)) + + def dictify(self) -> dict: + return dict(name=str(self), type=None, params=None) + + +class VersionBump(Enum): + NONE = auto() + MAJOR = auto() + MINOR = auto() + + +class ApiEntryState(Enum): + PENDING = "?" + APPROVED = "+" + DISABLED = "-" + # Special value for API version entry so users have less incentive to edit it + VERSION_PENDING = "v" + + +# Class that stores all known API entries, both enabled and disabled. +# Also keeps track of API versioning +# Allows comparison and update from newly-generated API +class SdkCache: + CSV_FIELD_NAMES = ("entry", "status", "name", "type", "params") + + def __init__(self, cache_file: str, load_version_only=False): + self.cache_file_name = cache_file + self.version = SdkVersion(0, 0) + self.sdk = ApiEntries() + self.disabled_entries = set() + self.new_entries = set() + self.loaded_dirty_version = False + + self.version_action = VersionBump.NONE + self._load_version_only = load_version_only + self.load_cache() + + def is_buildable(self) -> bool: + return ( + self.version != SdkVersion(0, 0) + and self.version_action == VersionBump.NONE + and not self._have_pending_entries() + ) + + def _filter_enabled(self, sdk_entries): + return sorted( + filter(lambda e: e not in self.disabled_entries, sdk_entries), + key=operator.attrgetter("name"), + ) + + def get_valid_names(self): + syms = set(map(lambda e: e.name, self.get_functions())) + syms.update(map(lambda e: e.name, self.get_variables())) + return syms + + def get_functions(self): + return self._filter_enabled(self.sdk.functions) + + def get_variables(self): + return self._filter_enabled(self.sdk.variables) + + def get_headers(self): + return self._filter_enabled(self.sdk.headers) + + def _get_entry_status(self, entry) -> str: + if entry in self.disabled_entries: + return ApiEntryState.DISABLED + elif entry in self.new_entries: + if isinstance(entry, SdkVersion): + return ApiEntryState.VERSION_PENDING + return ApiEntryState.PENDING + else: + return ApiEntryState.APPROVED + + def _format_entry(self, obj): + obj_dict = obj.dictify() + obj_dict.update( + dict( + entry=obj.csv_type, + status=self._get_entry_status(obj).value, + ) + ) + return obj_dict + + def save(self) -> None: + if self._load_version_only: + raise Exception("Only SDK version was loaded, cannot save") + + if self.version_action == VersionBump.MINOR: + self.version = SdkVersion(self.version.major, self.version.minor + 1) + elif self.version_action == VersionBump.MAJOR: + self.version = SdkVersion(self.version.major + 1, 0) + + if self._have_pending_entries(): + self.new_entries.add(self.version) + print( + f"API version is still WIP: {self.version}. Review the changes and re-run command." + ) + print(f"Entries to review:") + print( + "\n".join( + map( + str, + filter( + lambda e: not isinstance(e, SdkVersion), self.new_entries + ), + ) + ) + ) + else: + print(f"API version {self.version} is up to date") + + regenerate_csv = ( + self.loaded_dirty_version + or self._have_pending_entries() + or self.version_action != VersionBump.NONE + ) + + if regenerate_csv: + str_cache_entries = [self.version] + name_getter = operator.attrgetter("name") + str_cache_entries.extend(sorted(self.sdk.headers, key=name_getter)) + str_cache_entries.extend(sorted(self.sdk.functions, key=name_getter)) + str_cache_entries.extend(sorted(self.sdk.variables, key=name_getter)) + + with open(self.cache_file_name, "wt", newline="") as f: + writer = csv.DictWriter(f, fieldnames=SdkCache.CSV_FIELD_NAMES) + writer.writeheader() + + for entry in str_cache_entries: + writer.writerow(self._format_entry(entry)) + + def _process_entry(self, entry_dict: dict) -> None: + entry_class = entry_dict["entry"] + entry_status = entry_dict["status"] + entry_name = entry_dict["name"] + + entry = None + if entry_class == SdkVersion.csv_type: + self.version = SdkVersion.from_str(entry_name) + if entry_status == ApiEntryState.VERSION_PENDING.value: + self.loaded_dirty_version = True + elif entry_class == ApiHeader.csv_type: + self.sdk.headers.add(entry := ApiHeader(entry_name)) + elif entry_class == ApiEntryFunction.csv_type: + self.sdk.functions.add( + entry := ApiEntryFunction( + entry_name, + entry_dict["type"], + entry_dict["params"], + ) + ) + elif entry_class == ApiEntryVariable.csv_type: + self.sdk.variables.add( + entry := ApiEntryVariable(entry_name, entry_dict["type"]) + ) + else: + print(entry_dict) + raise Exception("Unknown entry type: %s" % entry_class) + + if entry is None: + return + + if entry_status == ApiEntryState.DISABLED.value: + self.disabled_entries.add(entry) + elif entry_status == ApiEntryState.PENDING.value: + self.new_entries.add(entry) + + def load_cache(self) -> None: + if not os.path.exists(self.cache_file_name): + raise Exception( + f"Cannot load symbol cache '{self.cache_file_name}'! File does not exist" + ) + + with open(self.cache_file_name, "rt") as f: + reader = csv.DictReader(f) + for row in reader: + self._process_entry(row) + if self._load_version_only and row.get("entry") == SdkVersion.csv_type: + break + + def _have_pending_entries(self) -> bool: + return any( + filter( + lambda e: not isinstance(e, SdkVersion), + self.new_entries, + ) + ) + + def sync_sets( + self, known_set: Set[Any], new_set: Set[Any], update_version: bool = True + ): + new_entries = new_set - known_set + if new_entries: + print(f"New: {new_entries}") + known_set |= new_entries + self.new_entries |= new_entries + if update_version and self.version_action == VersionBump.NONE: + self.version_action = VersionBump.MINOR + removed_entries = known_set - new_set + if removed_entries: + print(f"Removed: {removed_entries}") + known_set -= removed_entries + # If any of removed entries was a part of active API, that's a major bump + if update_version and any( + filter( + lambda e: e not in self.disabled_entries + and e not in self.new_entries, + removed_entries, + ) + ): + self.version_action = VersionBump.MAJOR + self.disabled_entries -= removed_entries + self.new_entries -= removed_entries + + def validate_api(self, api: ApiEntries) -> None: + self.sync_sets(self.sdk.headers, api.headers, False) + self.sync_sets(self.sdk.functions, api.functions) + self.sync_sets(self.sdk.variables, api.variables) diff --git a/site_scons/fbt/version.py b/site_scons/fbt/version.py index 4745c700..1b1c166f 100644 --- a/site_scons/fbt/version.py +++ b/site_scons/fbt/version.py @@ -1,7 +1,9 @@ import subprocess import datetime +from functools import cache +@cache def get_fast_git_version_id(): try: version = ( diff --git a/site_scons/site_init.py b/site_scons/site_init.py index 817269e2..2d83d881 100644 --- a/site_scons/site_init.py +++ b/site_scons/site_init.py @@ -5,6 +5,7 @@ import os import atexit sys.path.insert(0, os.path.join(os.getcwd(), "scripts")) +sys.path.insert(0, os.path.join(os.getcwd(), "lib/cxxheaderparser")) def bf_to_str(bf): diff --git a/site_scons/site_tools/blackmagic.py b/site_scons/site_tools/blackmagic.py index ec48c15f..0b114268 100644 --- a/site_scons/site_tools/blackmagic.py +++ b/site_scons/site_tools/blackmagic.py @@ -63,7 +63,7 @@ class BlackmagicResolver: if probe := self.get_serial() or self.get_networked(): return probe - raise Exception("Please specify BLACKMAGIC=...") + raise StopError("Please specify BLACKMAGIC=...") def generate(env): diff --git a/site_scons/site_tools/fbt_apps.py b/site_scons/site_tools/fbt_apps.py index 3dc35049..ef5e9b9d 100644 --- a/site_scons/site_tools/fbt_apps.py +++ b/site_scons/site_tools/fbt_apps.py @@ -18,18 +18,26 @@ from fbt.appmanifest import ( def LoadApplicationManifests(env): appmgr = env["APPMGR"] = AppManager() - for entry in env.Glob("#/applications/*", ondisk=True, source=True): - if isinstance(entry, SCons.Node.FS.Dir) and not str(entry).startswith("."): - try: - app_manifest_file_path = os.path.join(entry.abspath, "application.fam") - appmgr.load_manifest(app_manifest_file_path, entry.name) - env.Append(PY_LINT_SOURCES=[app_manifest_file_path]) - except FlipperManifestException as e: - warn(WarningOnByDefault, str(e)) + for app_dir, _ in env["APPDIRS"]: + app_dir_node = env.Dir("#").Dir(app_dir) + + for entry in app_dir_node.glob("*", ondisk=True, source=True): + if isinstance(entry, SCons.Node.FS.Dir) and not str(entry).startswith("."): + try: + app_manifest_file_path = os.path.join( + entry.abspath, "application.fam" + ) + appmgr.load_manifest(app_manifest_file_path, entry) + env.Append(PY_LINT_SOURCES=[app_manifest_file_path]) + except FlipperManifestException as e: + warn(WarningOnByDefault, str(e)) def PrepareApplicationsBuild(env): - env["APPBUILD"] = env["APPMGR"].filter_apps(env["APPS"]) + appbuild = env["APPBUILD"] = env["APPMGR"].filter_apps(env["APPS"]) + env.Append( + SDK_HEADERS=appbuild.get_sdk_headers(), + ) env["APPBUILD_DUMP"] = env.Action( DumpApplicationConfig, "\tINFO\t", diff --git a/site_scons/site_tools/fbt_assets.py b/site_scons/site_tools/fbt_assets.py index c844db36..87794847 100644 --- a/site_scons/site_tools/fbt_assets.py +++ b/site_scons/site_tools/fbt_assets.py @@ -13,11 +13,11 @@ def icons_emitter(target, source, env): "compiled/assets_icons.c", "compiled/assets_icons.h", ] + source = env.GlobRecursive("*.*", env["ICON_SRC_DIR"]) return target, source def proto_emitter(target, source, env): - out_path = target[0].path target = [] for src in source: basename = os.path.splitext(src.name)[0] @@ -109,7 +109,7 @@ def generate(env): BUILDERS={ "IconBuilder": Builder( action=Action( - '${PYTHON3} "${ASSETS_COMPILER}" icons ${SOURCE.posix} ${TARGET.dir.posix}', + '${PYTHON3} "${ASSETS_COMPILER}" icons ${ICON_SRC_DIR} ${TARGET.dir}', "${ICONSCOMSTR}", ), emitter=icons_emitter, diff --git a/site_scons/site_tools/fbt_dist.py b/site_scons/site_tools/fbt_dist.py index 399b7ecd..2b5c83df 100644 --- a/site_scons/site_tools/fbt_dist.py +++ b/site_scons/site_tools/fbt_dist.py @@ -4,7 +4,7 @@ from SCons.Script import Mkdir from SCons.Defaults import Touch -def get_variant_dirname(env, project=None): +def GetProjetDirName(env, project=None): parts = [f"f{env['TARGET_HW']}"] if project: parts.append(project) @@ -21,7 +21,7 @@ def get_variant_dirname(env, project=None): def create_fw_build_targets(env, configuration_name): - flavor = get_variant_dirname(env, configuration_name) + flavor = GetProjetDirName(env, configuration_name) build_dir = env.Dir("build").Dir(flavor).abspath return env.SConscript( "firmware.scons", @@ -49,7 +49,7 @@ def AddFwProject(env, base_env, fw_type, fw_env_key): ], ) - env.Replace(DIST_DIR=get_variant_dirname(env)) + env.Replace(DIST_DIR=env.GetProjetDirName()) return project_env @@ -115,6 +115,7 @@ def generate(env): env.AddMethod(AddFwProject) env.AddMethod(DistCommand) env.AddMethod(AddOpenOCDFlashTarget) + env.AddMethod(GetProjetDirName) env.AddMethod(AddJFlashTarget) env.AddMethod(AddUsbFlashTarget) diff --git a/site_scons/site_tools/fbt_extapps.py b/site_scons/site_tools/fbt_extapps.py index 17c4bf6c..4b584530 100644 --- a/site_scons/site_tools/fbt_extapps.py +++ b/site_scons/site_tools/fbt_extapps.py @@ -1,29 +1,151 @@ +from SCons.Builder import Builder +from SCons.Action import Action +from SCons.Errors import UserError +import SCons.Warnings + import os +import pathlib +from fbt.elfmanifest import assemble_manifest_data +from fbt.sdk import SdkCache +import itertools def BuildAppElf(env, app): work_dir = env.subst("$EXT_APPS_WORK_DIR") - app_target_name = os.path.join(work_dir, app.appid) + app_alias = f"{env['FIRMWARE_BUILD_CFG']}_{app.appid}" - app_elf = env.Program( - app_target_name, - env.GlobRecursive("*.c*", os.path.join(work_dir, app._appdir)), - APP_ENTRY=app.entry_point, + app_original_elf = os.path.join(work_dir, f"{app.appid}_d") + app_sources = list( + itertools.chain.from_iterable( + env.GlobRecursive(source_type, os.path.join(work_dir, app._appdir.relpath)) + for source_type in app.sources + ) ) - app_elf_dump = env.ObjDump(app_target_name) + app_elf_raw = env.Program( + app_original_elf, + app_sources, + APP_ENTRY=app.entry_point, + LIBS=env["LIBS"] + app.fap_libs, + ) + + app_elf_dump = env.ObjDump(app_elf_raw) env.Alias(f"{app_alias}_list", app_elf_dump) - app_stripped_elf = env.ELFStripper( - os.path.join(env.subst("$PLUGIN_ELF_DIR"), app.appid), app_elf + app_elf_augmented = env.EmbedAppMetadata( + os.path.join(env.subst("$PLUGIN_ELF_DIR"), app.appid), + app_elf_raw, + APP=app, ) - env.Alias(app_alias, app_stripped_elf) - return app_stripped_elf + + env.Depends(app_elf_augmented, [env["SDK_DEFINITION"], env.Value(app)]) + if app.fap_icon: + env.Depends( + app_elf_augmented, + env.File(f"{app._apppath}/{app.fap_icon}"), + ) + env.Alias(app_alias, app_elf_augmented) + + app_elf_import_validator = env.ValidateAppImports(app_elf_augmented) + env.AlwaysBuild(app_elf_import_validator) + return (app_elf_augmented, app_elf_raw, app_elf_import_validator) + + +def prepare_app_metadata(target, source, env): + sdk_cache = SdkCache(env.subst("$SDK_DEFINITION"), load_version_only=True) + + if not sdk_cache.is_buildable(): + raise UserError( + "SDK version is not finalized, please review changes and re-run operation" + ) + + app = env["APP"] + meta_file_name = source[0].path + ".meta" + with open(meta_file_name, "wb") as f: + # f.write(f"hello this is {app}") + f.write( + assemble_manifest_data( + app_manifest=app, + hardware_target=int(env.subst("$TARGET_HW")), + sdk_version=sdk_cache.version.as_int(), + ) + ) + + +def validate_app_imports(target, source, env): + sdk_cache = SdkCache(env.subst("$SDK_DEFINITION"), load_version_only=False) + app_syms = set() + with open(target[0].path, "rt") as f: + for line in f: + app_syms.add(line.split()[0]) + unresolved_syms = app_syms - sdk_cache.get_valid_names() + if unresolved_syms: + SCons.Warnings.warn( + SCons.Warnings.LinkWarning, + f"{source[0].path}: app won't run. Unresolved symbols: {unresolved_syms}", + ) + + +def GetExtAppFromPath(env, app_dir): + if not app_dir: + raise UserError("APPSRC= not set") + + appmgr = env["APPMGR"] + + app = None + for dir_part in reversed(pathlib.Path(app_dir).parts): + if app := appmgr.find_by_appdir(dir_part): + break + if not app: + raise UserError(f"Failed to resolve application for given APPSRC={app_dir}") + + app_elf = env["_extapps"]["compact"].get(app.appid, None) + if not app_elf: + raise UserError(f"No external app found for {app.appid}") + + return (app, app_elf[0]) def generate(env, **kw): - env.SetDefault(EXT_APPS_WORK_DIR=kw.get("EXT_APPS_WORK_DIR", ".extapps")) - env.VariantDir(env.subst("$EXT_APPS_WORK_DIR"), ".", duplicate=False) + env.SetDefault(EXT_APPS_WORK_DIR=kw.get("EXT_APPS_WORK_DIR")) + env.VariantDir(env.subst("$EXT_APPS_WORK_DIR"), env.Dir("#"), duplicate=False) + env.AddMethod(BuildAppElf) + env.AddMethod(GetExtAppFromPath) + env.Append( + BUILDERS={ + "EmbedAppMetadata": Builder( + action=[ + Action(prepare_app_metadata, "$APPMETA_COMSTR"), + Action( + "${OBJCOPY} " + "--remove-section .ARM.attributes " + "--add-section .fapmeta=${SOURCE}.meta " + "--set-section-flags .fapmeta=contents,noload,readonly,data " + "--strip-debug --strip-unneeded " + "--add-gnu-debuglink=${SOURCE} " + "${SOURCES} ${TARGET}", + "$APPMETAEMBED_COMSTR", + ), + ], + suffix=".fap", + src_suffix=".elf", + ), + "ValidateAppImports": Builder( + action=[ + Action( + "@${NM} -P -u ${SOURCE} > ${TARGET}", + None, # "$APPDUMP_COMSTR", + ), + Action( + validate_app_imports, + None, # "$APPCHECK_COMSTR", + ), + ], + suffix=".impsyms", + src_suffix=".fap", + ), + } + ) def exists(env): diff --git a/site_scons/site_tools/fbt_sdk.py b/site_scons/site_tools/fbt_sdk.py new file mode 100644 index 00000000..f6c2d452 --- /dev/null +++ b/site_scons/site_tools/fbt_sdk.py @@ -0,0 +1,209 @@ +from SCons.Builder import Builder +from SCons.Action import Action +from SCons.Errors import UserError + +# from SCons.Scanner import C +from SCons.Script import Mkdir, Copy, Delete, Entry +from SCons.Util import LogicalLines + +import os.path +import posixpath +import pathlib + +from fbt.sdk import SdkCollector, SdkCache + + +def prebuild_sdk_emitter(target, source, env): + target.append(env.ChangeFileExtension(target[0], ".d")) + target.append(env.ChangeFileExtension(target[0], ".i.c")) + return target, source + + +def prebuild_sdk_create_origin_file(target, source, env): + mega_file = env.subst("${TARGET}.c", target=target[0]) + with open(mega_file, "wt") as sdk_c: + sdk_c.write("\n".join(f"#include <{h.path}>" for h in env["SDK_HEADERS"])) + + +class SdkTreeBuilder: + def __init__(self, env, target, source) -> None: + self.env = env + self.target = target + self.source = source + + self.header_depends = [] + self.header_dirs = [] + + self.target_sdk_dir = env.subst("f${TARGET_HW}_sdk") + self.sdk_deploy_dir = target[0].Dir(self.target_sdk_dir) + + def _parse_sdk_depends(self): + deps_file = self.source[0] + with open(deps_file.path, "rt") as deps_f: + lines = LogicalLines(deps_f).readlines() + _, depends = lines[0].split(":", 1) + self.header_depends = list( + filter(lambda fname: fname.endswith(".h"), depends.split()), + ) + self.header_dirs = sorted( + set(map(os.path.normpath, map(os.path.dirname, self.header_depends))) + ) + + def _generate_sdk_meta(self): + filtered_paths = [self.target_sdk_dir] + full_fw_paths = list( + map( + os.path.normpath, + (self.env.Dir(inc_dir).relpath for inc_dir in self.env["CPPPATH"]), + ) + ) + + sdk_dirs = ", ".join(f"'{dir}'" for dir in self.header_dirs) + for dir in full_fw_paths: + if dir in sdk_dirs: + filtered_paths.append( + posixpath.normpath(posixpath.join(self.target_sdk_dir, dir)) + ) + + sdk_env = self.env.Clone() + sdk_env.Replace(CPPPATH=filtered_paths) + with open(self.target[0].path, "wt") as f: + cmdline_options = sdk_env.subst( + "$CCFLAGS $_CCCOMCOM", target=Entry("dummy") + ) + f.write(cmdline_options.replace("\\", "/")) + f.write("\n") + + def _create_deploy_commands(self): + dirs_to_create = set( + self.sdk_deploy_dir.Dir(dirpath) for dirpath in self.header_dirs + ) + actions = [ + Delete(self.sdk_deploy_dir), + Mkdir(self.sdk_deploy_dir), + ] + actions += [Mkdir(d) for d in dirs_to_create] + + actions += [ + Copy( + self.sdk_deploy_dir.File(h).path, + h, + ) + for h in self.header_depends + ] + return actions + + def generate_actions(self): + self._parse_sdk_depends() + self._generate_sdk_meta() + + return self._create_deploy_commands() + + +def deploy_sdk_tree(target, source, env, for_signature): + if for_signature: + return [] + + sdk_tree = SdkTreeBuilder(env, target, source) + return sdk_tree.generate_actions() + + +def gen_sdk_data(sdk_cache: SdkCache): + api_def = [] + api_def.extend( + (f"#include <{h.name}>" for h in sdk_cache.get_headers()), + ) + + api_def.append(f"const int elf_api_version = {sdk_cache.version.as_int()};") + + api_def.append( + "static constexpr auto elf_api_table = sort(create_array_t(" + ) + + api_lines = [] + for fun_def in sdk_cache.get_functions(): + api_lines.append( + f"API_METHOD({fun_def.name}, {fun_def.returns}, ({fun_def.params}))" + ) + + for var_def in sdk_cache.get_variables(): + api_lines.append(f"API_VARIABLE({var_def.name}, {var_def.var_type })") + + api_def.append(",\n".join(api_lines)) + + api_def.append("));") + return api_def + + +def _check_sdk_is_up2date(sdk_cache: SdkCache): + if not sdk_cache.is_buildable(): + raise UserError( + "SDK version is not finalized, please review changes and re-run operation" + ) + + +def validate_sdk_cache(source, target, env): + # print(f"Generating SDK for {source[0]} to {target[0]}") + current_sdk = SdkCollector() + current_sdk.process_source_file_for_sdk(source[0].path) + for h in env["SDK_HEADERS"]: + current_sdk.add_header_to_sdk(pathlib.Path(h.path).as_posix()) + + sdk_cache = SdkCache(target[0].path) + sdk_cache.validate_api(current_sdk.get_api()) + sdk_cache.save() + _check_sdk_is_up2date(sdk_cache) + + +def generate_sdk_symbols(source, target, env): + sdk_cache = SdkCache(source[0].path) + _check_sdk_is_up2date(sdk_cache) + + api_def = gen_sdk_data(sdk_cache) + with open(target[0].path, "wt") as f: + f.write("\n".join(api_def)) + + +def generate(env, **kw): + env.Append( + BUILDERS={ + "SDKPrebuilder": Builder( + emitter=prebuild_sdk_emitter, + action=[ + Action( + prebuild_sdk_create_origin_file, + "$SDK_PREGEN_COMSTR", + ), + Action( + "$CC -o $TARGET -E -P $CCFLAGS $_CCCOMCOM $SDK_PP_FLAGS -MMD ${TARGET}.c", + "$SDK_COMSTR", + ), + ], + suffix=".i", + ), + "SDKTree": Builder( + generator=deploy_sdk_tree, + src_suffix=".d", + ), + "SDKSymUpdater": Builder( + action=Action( + validate_sdk_cache, + "$SDKSYM_UPDATER_COMSTR", + ), + suffix=".csv", + src_suffix=".i", + ), + "SDKSymGenerator": Builder( + action=Action( + generate_sdk_symbols, + "$SDKSYM_GENERATOR_COMSTR", + ), + suffix=".h", + src_suffix=".csv", + ), + } + ) + + +def exists(env): + return True diff --git a/site_scons/site_tools/fwbin.py b/site_scons/site_tools/fwbin.py index 37e64e56..678b0499 100644 --- a/site_scons/site_tools/fwbin.py +++ b/site_scons/site_tools/fwbin.py @@ -3,12 +3,14 @@ from SCons.Action import Action import SCons __OBJCOPY_ARM_BIN = "arm-none-eabi-objcopy" +__NM_ARM_BIN = "arm-none-eabi-nm" def generate(env): env.SetDefault( BIN2DFU="${ROOT_DIR.abspath}/scripts/bin2dfu.py", OBJCOPY=__OBJCOPY_ARM_BIN, # FIXME + NM=__NM_ARM_BIN, # FIXME ) env.Append( BUILDERS={ diff --git a/site_scons/site_tools/sconsmodular.py b/site_scons/site_tools/sconsmodular.py index 778c664e..b115706c 100644 --- a/site_scons/site_tools/sconsmodular.py +++ b/site_scons/site_tools/sconsmodular.py @@ -40,10 +40,15 @@ def PhonyTarget(env, name, action, source=None, **kw): return command +def ChangeFileExtension(env, fnode, ext): + return env.File(f"#{os.path.splitext(fnode.path)[0]}{ext}") + + def generate(env): env.AddMethod(BuildModule) env.AddMethod(BuildModules) env.AddMethod(PhonyTarget) + env.AddMethod(ChangeFileExtension) def exists(env):