Przeglądaj źródła

Merge branch 'dev' of github.com:0xchocolate/flipperzero-firmware-with-wifi-marauder-companion into feature_wifi_marauder_app

0xchocolate 3 lat temu
rodzic
commit
9269c2dfe7
100 zmienionych plików z 1022 dodań i 271 usunięć
  1. 128 23
      .clang-format
  2. 12 37
      .github/workflows/amap_analyse.yml
  3. 43 59
      .github/workflows/build.yml
  4. 2 4
      .github/workflows/check_submodules.yml
  5. 2 4
      .github/workflows/lint_c.yml
  6. 2 4
      .github/workflows/lint_python.yml
  7. 19 24
      .github/workflows/pvs_studio.yml
  8. 3 0
      .gitmodules
  9. 10 3
      .vscode/example/launch.json
  10. 3 0
      .vscode/example/settings.json
  11. 30 0
      .vscode/example/tasks.json
  12. 4 0
      ReadMe.md
  13. 28 4
      SConstruct
  14. 71 19
      applications/ReadMe.md
  15. 0 66
      applications/bt/application.fam
  16. 0 0
      applications/debug/accessor/accessor.cpp
  17. 0 0
      applications/debug/accessor/accessor_app.cpp
  18. 0 0
      applications/debug/accessor/accessor_app.h
  19. 0 0
      applications/debug/accessor/accessor_event.h
  20. 0 0
      applications/debug/accessor/accessor_view_manager.cpp
  21. 0 0
      applications/debug/accessor/accessor_view_manager.h
  22. 1 0
      applications/debug/accessor/application.fam
  23. 0 0
      applications/debug/accessor/helpers/wiegand.cpp
  24. 0 0
      applications/debug/accessor/helpers/wiegand.h
  25. 0 0
      applications/debug/accessor/scene/accessor_scene_generic.h
  26. 0 0
      applications/debug/accessor/scene/accessor_scene_start.cpp
  27. 0 0
      applications/debug/accessor/scene/accessor_scene_start.h
  28. 16 0
      applications/debug/application.fam
  29. 14 0
      applications/debug/battery_test_app/application.fam
  30. 5 5
      applications/debug/battery_test_app/battery_test_app.c
  31. 3 2
      applications/debug/battery_test_app/battery_test_app.h
  32. 11 0
      applications/debug/blink_test/application.fam
  33. 0 0
      applications/debug/blink_test/blink_test.c
  34. 18 0
      applications/debug/bt_debug_app/application.fam
  35. 0 0
      applications/debug/bt_debug_app/bt_debug_app.c
  36. 1 1
      applications/debug/bt_debug_app/bt_debug_app.h
  37. 0 0
      applications/debug/bt_debug_app/views/bt_carrier_test.c
  38. 0 0
      applications/debug/bt_debug_app/views/bt_carrier_test.h
  39. 0 0
      applications/debug/bt_debug_app/views/bt_packet_test.c
  40. 0 0
      applications/debug/bt_debug_app/views/bt_packet_test.h
  41. 0 0
      applications/debug/bt_debug_app/views/bt_test.c
  42. 0 0
      applications/debug/bt_debug_app/views/bt_test.h
  43. 0 0
      applications/debug/bt_debug_app/views/bt_test_types.h
  44. 11 0
      applications/debug/display_test/application.fam
  45. 0 0
      applications/debug/display_test/display_test.c
  46. 0 0
      applications/debug/display_test/display_test.h
  47. 0 0
      applications/debug/display_test/view_display_test.c
  48. 0 0
      applications/debug/display_test/view_display_test.h
  49. 11 0
      applications/debug/file_browser_test/application.fam
  50. 0 0
      applications/debug/file_browser_test/file_browser_app.c
  51. 0 0
      applications/debug/file_browser_test/file_browser_app_i.h
  52. 0 0
      applications/debug/file_browser_test/scenes/file_browser_scene.c
  53. 0 0
      applications/debug/file_browser_test/scenes/file_browser_scene.h
  54. 0 0
      applications/debug/file_browser_test/scenes/file_browser_scene_browser.c
  55. 0 0
      applications/debug/file_browser_test/scenes/file_browser_scene_config.h
  56. 0 0
      applications/debug/file_browser_test/scenes/file_browser_scene_result.c
  57. 0 0
      applications/debug/file_browser_test/scenes/file_browser_scene_start.c
  58. 11 0
      applications/debug/keypad_test/application.fam
  59. 0 0
      applications/debug/keypad_test/keypad_test.c
  60. 4 1
      applications/debug/lfrfid_debug/application.fam
  61. 81 0
      applications/debug/lfrfid_debug/lfrfid_debug.c
  62. 30 0
      applications/debug/lfrfid_debug/lfrfid_debug_i.h
  63. 44 0
      applications/debug/lfrfid_debug/scenes/lfrfid_debug_app_scene_start.c
  64. 17 11
      applications/debug/lfrfid_debug/scenes/lfrfid_debug_app_scene_tune.c
  65. 30 0
      applications/debug/lfrfid_debug/scenes/lfrfid_debug_scene.c
  66. 29 0
      applications/debug/lfrfid_debug/scenes/lfrfid_debug_scene.h
  67. 2 0
      applications/debug/lfrfid_debug/scenes/lfrfid_debug_scene_config.h
  68. 229 0
      applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.c
  69. 18 0
      applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.h
  70. 11 0
      applications/debug/text_box_test/application.fam
  71. 0 0
      applications/debug/text_box_test/text_box_test.c
  72. 11 0
      applications/debug/uart_echo/application.fam
  73. 0 0
      applications/debug/uart_echo/uart_echo.c
  74. 1 1
      applications/debug/unit_tests/application.fam
  75. 0 0
      applications/debug/unit_tests/flipper_format/flipper_format_string_test.c
  76. 0 0
      applications/debug/unit_tests/flipper_format/flipper_format_test.c
  77. 0 0
      applications/debug/unit_tests/furi/furi_memmgr_test.c
  78. 0 0
      applications/debug/unit_tests/furi/furi_pubsub_test.c
  79. 0 0
      applications/debug/unit_tests/furi/furi_record_test.c
  80. 0 0
      applications/debug/unit_tests/furi/furi_test.c
  81. 0 0
      applications/debug/unit_tests/furi/furi_valuemutex_test.c
  82. 0 0
      applications/debug/unit_tests/infrared/infrared_test.c
  83. 0 0
      applications/debug/unit_tests/lfrfid/bit_lib_test.c
  84. 0 0
      applications/debug/unit_tests/lfrfid/lfrfid_protocols.c
  85. 0 0
      applications/debug/unit_tests/minunit.h
  86. 0 0
      applications/debug/unit_tests/minunit_vars.h
  87. 0 0
      applications/debug/unit_tests/minunit_vars_ex.h
  88. 1 1
      applications/debug/unit_tests/nfc/nfc_test.c
  89. 0 0
      applications/debug/unit_tests/protocol_dict/protocol_dict_test.c
  90. 0 0
      applications/debug/unit_tests/rpc/rpc_test.c
  91. 0 0
      applications/debug/unit_tests/storage/dirwalk_test.c
  92. 0 0
      applications/debug/unit_tests/storage/storage_test.c
  93. 0 0
      applications/debug/unit_tests/stream/stream_test.c
  94. 33 2
      applications/debug/unit_tests/subghz/subghz_test.c
  95. 0 0
      applications/debug/unit_tests/test_index.c
  96. 0 0
      applications/debug/unit_tests/varint/varint_test.c
  97. 11 0
      applications/debug/usb_mouse/application.fam
  98. 0 0
      applications/debug/usb_mouse/usb_mouse.c
  99. 11 0
      applications/debug/usb_test/application.fam
  100. 0 0
      applications/debug/usb_test/usb_test.c

+ 128 - 23
.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
+...
+

+ 12 - 37
.github/workflows/amap_analyse.yml

@@ -35,8 +35,7 @@ jobs:
       - name: 'Decontaminate previous build leftovers'
         run: |
           if [ -d .git ]; then
-            git submodule status \
-              || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1`
+            git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)"
           fi
 
       - name: 'Checkout code'
@@ -45,32 +44,16 @@ jobs:
           fetch-depth: 0
           ref: ${{ github.event.pull_request.head.sha }}
 
-      - name: 'Generate prefixes by commit'
-        id: names
+      - name: 'Get commit details'
         run: |
-          REF="${{github.ref}}"
-          COMMIT_HASH="$(git rev-parse HEAD)"
-          SHA="$(git rev-parse --short HEAD)"
-          COMMIT_MSG="${{github.event.head_commit.message}}"
           if [[ ${{ github.event_name }} == 'pull_request' ]]; then
-            REF="${{github.head_ref}}"
-            COMMIT_HASH="$(git log -1 --pretty=oneline | awk '{print $1}')"
-            SHA="$(cut -c -8 <<< "$COMMIT_HASH")"
-            COMMIT_MSG="$(git log -1 --pretty=format:"%s")"
-            PULL_ID="${{github.event.pull_request.number}}"
-            PULL_NAME="${{github.event.pull_request.title}}"
+            TYPE="pull"
+          elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
+            TYPE="tag"
+          else
+            TYPE="other"
           fi
-          BRANCH_NAME=${REF#refs/*/}
-          SUFFIX=${BRANCH_NAME//\//_}-$(date +'%d%m%Y')-${SHA}
-          if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
-            SUFFIX=${BRANCH_NAME//\//_}
-          fi
-          echo "::set-output name=commit-hash::${COMMIT_HASH}"
-          echo "::set-output name=commit-msg::${COMMIT_MSG}"
-          echo "::set-output name=pull-id::${PULL_ID}"
-          echo "::set-output name=pull-name::${PULL_NAME}"
-          echo "::set-output name=branch-name::${BRANCH_NAME}"
-          echo "::set-output name=suffix::${SUFFIX}"
+          python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE"
 
       - name: 'Make artifacts directory'
         run: |
@@ -78,19 +61,18 @@ jobs:
           mkdir artifacts
 
       - name: 'Download build artifacts'
-        if: ${{ !github.event.pull_request.head.repo.fork }}
         run: |
           echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key;
           chmod 600 ./deploy_key;
           rsync -avzP \
               -e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \
-              ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${{steps.names.outputs.branch-name}}/" artifacts/;
+              ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${BRANCH_NAME}/" artifacts/;
           rm ./deploy_key;
 
       - name: 'Make .map file analyze'
         run: |
           cd artifacts/
-          /Applications/amap/Contents/MacOS/amap -f flipper-z-f7-firmware-${{steps.names.outputs.suffix}}.elf.map
+          /Applications/amap/Contents/MacOS/amap -f "flipper-z-f7-firmware-${SUFFIX}.elf.map"
 
       - name: 'Upload report to DB'
         run: |
@@ -99,21 +81,14 @@ jobs:
           {
             SECTION="$1";
             arm-none-eabi-size \
-              -A artifacts/flipper-z-f7-firmware-${{steps.names.outputs.suffix}}.elf \
+              -A artifacts/flipper-z-f7-firmware-$SUFFIX.elf \
               | grep "^$SECTION" | awk '{print $2}'
           }
-          export COMMIT_HASH="${{steps.names.outputs.commit-hash}}"
-          export COMMIT_MSG="${{steps.names.outputs.commit-msg}}"
-          export BRANCH_NAME="${{steps.names.outputs.branch-name}}"
           export BSS_SIZE="$(get_size ".bss")"
           export TEXT_SIZE="$(get_size ".text")"
           export RODATA_SIZE="$(get_size ".rodata")"
           export DATA_SIZE="$(get_size ".data")"
           export FREE_FLASH_SIZE="$(get_size ".free_flash")"
-          if [[ ${{ github.event_name }} == 'pull_request' ]]; then
-            export PULL_ID="${{steps.names.outputs.pull-id}}"
-            export PULL_NAME="${{steps.names.outputs.pull-name}}"
-          fi
           python3 -m pip install mariadb
           python3 scripts/amap_mariadb_insert.py \
             ${{ secrets.AMAP_MARIADB_USER }} \
@@ -121,4 +96,4 @@ jobs:
             ${{ secrets.AMAP_MARIADB_HOST }} \
             ${{ secrets.AMAP_MARIADB_PORT }} \
             ${{ secrets.AMAP_MARIADB_DATABASE }} \
-            artifacts/flipper-z-f7-firmware-${{steps.names.outputs.suffix}}.elf.map.all
+            artifacts/flipper-z-f7-firmware-$SUFFIX.elf.map.all

+ 43 - 59
.github/workflows/build.yml

@@ -19,10 +19,8 @@ jobs:
     steps:
       - name: 'Decontaminate previous build leftovers'
         run: |
-          if [ -d .git ]
-          then
-            git submodule status \
-              || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1`
+          if [ -d .git ]; then
+            git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)"
           fi
 
       - name: 'Checkout code'
@@ -33,51 +31,46 @@ jobs:
 
       - name: 'Make artifacts directory'
         run: |
-          test -d artifacts && rm -rf artifacts || true
+          rm -rf artifacts
           mkdir artifacts
 
-      - name: 'Generate suffix and folder name'
-        id: names
+      - name: 'Get commit details'
         run: |
-          REF=${{ github.ref }}
           if [[ ${{ github.event_name }} == 'pull_request' ]]; then
-            REF=${{ github.head_ref }}
-          fi
-          BRANCH_OR_TAG=${REF#refs/*/}
-          SHA=$(git rev-parse --short HEAD)
-
-          if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
-            SUFFIX=${BRANCH_OR_TAG//\//_}
+            TYPE="pull"
+          elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
+            TYPE="tag"
           else
-            SUFFIX=${BRANCH_OR_TAG//\//_}-$(date +'%d%m%Y')-${SHA}
+            TYPE="other"
           fi
+          python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE"
 
-          echo "WORKFLOW_BRANCH_OR_TAG=${BRANCH_OR_TAG}" >> $GITHUB_ENV
-          echo "DIST_SUFFIX=${SUFFIX}" >> $GITHUB_ENV
-          echo "::set-output name=artifacts-path::${BRANCH_OR_TAG}"
+      - name: 'Generate suffixes for comment'
+        id: names
+        run: |
+          echo "::set-output name=branch_name::${BRANCH_NAME}"
+          echo "::set-output name=commit_sha::${COMMIT_SHA}"
+          echo "::set-output name=default_target::${DEFAULT_TARGET}"
           echo "::set-output name=suffix::${SUFFIX}"
-          echo "::set-output name=short-hash::${SHA}"
-          echo "::set-output name=default-target::${DEFAULT_TARGET}"
 
       - name: 'Bundle scripts'
         if: ${{ !github.event.pull_request.head.repo.fork }}
         run: |
-          tar czpf artifacts/flipper-z-any-scripts-${{steps.names.outputs.suffix}}.tgz scripts
+          tar czpf artifacts/flipper-z-any-scripts-${SUFFIX}.tgz scripts
 
       - name: 'Build the firmware'
         run: |
           set -e
-          for TARGET in ${TARGETS}
-          do
-            FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }}
+          for TARGET in ${TARGETS}; do
+            FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW="$(echo "${TARGET}" | sed 's/f//')" \
+                updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }}
           done
 
       - name: 'Move upload files'
         if: ${{ !github.event.pull_request.head.repo.fork }}
         run: |
           set -e
-          for TARGET in ${TARGETS}
-          do
+          for TARGET in ${TARGETS}; do
             mv dist/${TARGET}-*/* artifacts/
           done
 
@@ -85,12 +78,11 @@ jobs:
         if: ${{ !github.event.pull_request.head.repo.fork }}
         run: |
           set -e
-          for UPDATEBUNDLE in artifacts/*/
-          do
-            BUNDLE_NAME=`echo $UPDATEBUNDLE | cut -d'/' -f2`
-            echo Packaging ${BUNDLE_NAME}
-            tar czpf artifacts/flipper-z-${BUNDLE_NAME}.tgz -C artifacts ${BUNDLE_NAME}
-            rm -rf artifacts/${BUNDLE_NAME}
+          for UPDATEBUNDLE in artifacts/*/; do
+            BUNDLE_NAME="$(echo "$UPDATEBUNDLE" | cut -d'/' -f2)"
+            echo Packaging "${BUNDLE_NAME}"
+            tar czpf "artifacts/flipper-z-${BUNDLE_NAME}.tgz" -C artifacts "${BUNDLE_NAME}"
+            rm -rf "artifacts/${BUNDLE_NAME}"
           done
 
       - name: "Check for uncommitted changes"
@@ -100,17 +92,17 @@ jobs:
       - name: 'Bundle resources'
         if: ${{ !github.event.pull_request.head.repo.fork }}
         run: |
-          tar czpf artifacts/flipper-z-any-resources-${{steps.names.outputs.suffix}}.tgz -C assets resources
+          tar czpf "artifacts/flipper-z-any-resources-${SUFFIX}.tgz" -C assets resources
 
       - name: 'Bundle core2 firmware'
         if: ${{ !github.event.pull_request.head.repo.fork }}
         run: |
           FBT_TOOLCHAIN_PATH=/opt ./fbt copro_dist
-          tar czpf artifacts/flipper-z-any-core2_firmware-${{steps.names.outputs.suffix}}.tgz -C assets core2_firmware
+          tar czpf "artifacts/flipper-z-any-core2_firmware-${SUFFIX}.tgz" -C assets core2_firmware
 
       - name: 'Copy .map file'
         run: |
-          cp build/f7-firmware-*/firmware.elf.map artifacts/flipper-z-f7-firmware-${{steps.names.outputs.suffix}}.elf.map
+          cp build/f7-firmware-*/firmware.elf.map "artifacts/flipper-z-f7-firmware-${SUFFIX}.elf.map"
 
       - name: 'Upload artifacts to update server'
         if: ${{ !github.event.pull_request.head.repo.fork }}
@@ -119,7 +111,7 @@ jobs:
           chmod 600 ./deploy_key;
           rsync -avzP --delete --mkpath \
               -e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \
-              artifacts/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${{steps.names.outputs.artifacts-path}}/";
+              artifacts/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${BRANCH_NAME}/";
           rm ./deploy_key;
 
       - name: 'Trigger update server reindex'
@@ -142,10 +134,10 @@ jobs:
           comment-id: ${{ steps.fc.outputs.comment-id }}
           issue-number: ${{ github.event.pull_request.number }}
           body: |
-            **Compiled firmware for commit `${{steps.names.outputs.short-hash}}`:**
-            - [📦 Update package](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.artifacts-path}}/flipper-z-${{steps.names.outputs.default-target}}-update-${{steps.names.outputs.suffix}}.tgz)
-            - [📥 DFU file](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.artifacts-path}}/flipper-z-${{steps.names.outputs.default-target}}-full-${{steps.names.outputs.suffix}}.dfu)
-            - [☁️ Web updater](https://my.flipp.dev/?url=https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.artifacts-path}}/flipper-z-${{steps.names.outputs.default-target}}-update-${{steps.names.outputs.suffix}}.tgz&channel=${{steps.names.outputs.artifacts-path}}&version=${{steps.names.outputs.short-hash}})
+            **Compiled firmware for commit `${{steps.names.outputs.commit_sha}}`:**
+            - [📦 Update package](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz)
+            - [📥 DFU file](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-full-${{steps.names.outputs.suffix}}.dfu)
+            - [☁️ Web updater](https://my.flipp.dev/?url=https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz&channel=${{steps.names.outputs.branch_name}}&version=${{steps.names.outputs.commit_sha}})
           edit-mode: replace
 
   compact:
@@ -157,7 +149,7 @@ jobs:
           if [ -d .git ]
           then
             git submodule status \
-              || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1`
+              || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)"
           fi
 
       - name: 'Checkout code'
@@ -167,29 +159,21 @@ jobs:
           submodules: true
           ref: ${{ github.event.pull_request.head.sha }}
 
-      - name: 'Generate suffix and folder name'
-        id: names
+      - name: 'Get commit details'
         run: |
-          REF=${{ github.ref }}
           if [[ ${{ github.event_name }} == 'pull_request' ]]; then
-            REF=${{ github.head_ref }}
-          fi
-          BRANCH_OR_TAG=${REF#refs/*/}
-          SHA=$(git rev-parse --short HEAD)
-
-          if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
-            SUFFIX=${BRANCH_OR_TAG//\//_}
+            TYPE="pull"
+          elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
+            TYPE="tag"
           else
-            SUFFIX=${BRANCH_OR_TAG//\//_}-$(date +'%d%m%Y')-${SHA}
+            TYPE="other"
           fi
-
-          echo "WORKFLOW_BRANCH_OR_TAG=${BRANCH_OR_TAG}" >> $GITHUB_ENV
-          echo "DIST_SUFFIX=${SUFFIX}" >> $GITHUB_ENV
+          python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE"
 
       - name: 'Build the firmware'
         run: |
           set -e
-          for TARGET in ${TARGETS}
-          do
-            FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package DEBUG=0 COMPACT=1
+          for TARGET in ${TARGETS}; do
+            FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW="$(echo "${TARGET}" | sed 's/f//')" \
+                updater_package DEBUG=0 COMPACT=1
           done

+ 2 - 4
.github/workflows/check_submodules.yml

@@ -15,10 +15,8 @@ jobs:
     steps:
       - name: 'Decontaminate previous build leftovers'
         run: |
-          if [ -d .git ]
-          then
-            git submodule status \
-              || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1`
+          if [ -d .git ]; then
+            git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)"
           fi
 
       - name: 'Checkout code'

+ 2 - 4
.github/workflows/lint_c.yml

@@ -18,10 +18,8 @@ jobs:
     steps:
       - name: 'Decontaminate previous build leftovers'
         run: |
-          if [ -d .git ]
-          then
-            git submodule status \
-              || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1`
+          if [ -d .git ]; then
+            git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)"
           fi
 
       - name: 'Checkout code'

+ 2 - 4
.github/workflows/lint_python.yml

@@ -15,10 +15,8 @@ jobs:
     steps:
       - name: 'Decontaminate previous build leftovers'
         run: |
-          if [ -d .git ]
-          then
-            git submodule status \
-              || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1`
+          if [ -d .git ]; then
+            git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)"
           fi
 
       - name: 'Checkout code'

+ 19 - 24
.github/workflows/pvs_studio.yml

@@ -20,10 +20,8 @@ jobs:
     steps:
       - name: 'Decontaminate previous build leftovers'
         run: |
-          if [ -d .git ]
-          then
-            git submodule status \
-              || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1`
+          if [ -d .git ]; then
+            git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)"
           fi
 
       - name: 'Checkout code'
@@ -32,28 +30,25 @@ jobs:
           fetch-depth: 0
           ref: ${{ github.event.pull_request.head.sha }}
 
-      - name: 'Generate suffix and folder name'
-        id: names
+      - name: 'Get commit details'
         run: |
-          REF=${{ github.ref }}
           if [[ ${{ github.event_name }} == 'pull_request' ]]; then
-            REF=${{ github.head_ref }}
-          fi
-          BRANCH_OR_TAG=${REF#refs/*/}
-          SHA=$(git rev-parse --short HEAD)
-
-          if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
-            SUFFIX=${BRANCH_OR_TAG//\//_}
+            TYPE="pull"
+          elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
+            TYPE="tag"
           else
-            SUFFIX=${BRANCH_OR_TAG//\//_}-$(date +'%d%m%Y')-${SHA}
+            TYPE="other"
           fi
+          python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE"
 
-          echo "WORKFLOW_BRANCH_OR_TAG=${BRANCH_OR_TAG}" >> $GITHUB_ENV
-          echo "DIST_SUFFIX=${SUFFIX}" >> $GITHUB_ENV
-          echo "::set-output name=artifacts-path::${BRANCH_OR_TAG}"
+      - name: 'Generate suffixes for comment'
+        if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request }}
+        id: names
+        run: |
+          echo "::set-output name=branch_name::${BRANCH_NAME}"
+          echo "::set-output name=commit_sha::${COMMIT_SHA}"
+          echo "::set-output name=default_target::${DEFAULT_TARGET}"
           echo "::set-output name=suffix::${SUFFIX}"
-          echo "::set-output name=short-hash::${SHA}"
-          echo "::set-output name=default-target::${DEFAULT_TARGET}"
 
       - name: 'Make reports directory'
         run: |
@@ -75,7 +70,7 @@ jobs:
               -o PVS-Studio.log
 
       - name: 'Convert PVS-Studio output to html page'
-        run: plog-converter -a GA:1,2,3 -t fullhtml PVS-Studio.log -o reports/${{steps.names.outputs.default-target}}-${{steps.names.outputs.suffix}}
+        run: plog-converter -a GA:1,2,3 -t fullhtml PVS-Studio.log -o reports/${DEFAULT_TARGET}-${SUFFIX}
 
       - name: 'Upload artifacts to update server'
         if: ${{ !github.event.pull_request.head.repo.fork }}
@@ -84,7 +79,7 @@ jobs:
           chmod 600 ./deploy_key;
           rsync -avrzP --mkpath \
               -e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \
-              reports/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:/home/data/firmware-pvs-studio-report/"${{steps.names.outputs.artifacts-path}}/";
+              reports/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:/home/data/firmware-pvs-studio-report/"${BRANCH_NAME}/";
           rm ./deploy_key;
 
       - name: 'Find Previous Comment'
@@ -103,6 +98,6 @@ jobs:
           comment-id: ${{ steps.fc.outputs.comment-id }}
           issue-number: ${{ github.event.pull_request.number }}
           body: |
-            **PVS-Studio report for commit `${{steps.names.outputs.short-hash}}`:**
-            - [Report](https://update.flipperzero.one/builds/firmware-pvs-studio-report/${{steps.names.outputs.artifacts-path}}/${{steps.names.outputs.default-target}}-${{steps.names.outputs.suffix}}/index.html)
+            **PVS-Studio report for commit `${{steps.names.outputs.commit_sha}}`:**
+            - [Report](https://update.flipperzero.one/builds/firmware-pvs-studio-report/${{steps.names.outputs.branch_name}}/${{steps.names.outputs.default_target}}-${{steps.names.outputs.suffix}}/index.html)
           edit-mode: replace

+ 3 - 0
.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

+ 10 - 3
.vscode/example/launch.json

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

+ 3 - 0
.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",
     "editor.formatOnSave": true,
     "files.associations": {
         "*.scons": "python",

+ 30 - 0
.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}"
+        }
     ]
 }

+ 4 - 0
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/)

+ 28 - 4
SConstruct

@@ -1,5 +1,5 @@
 #
-# Main Fipper Build System entry point
+# Main Flipper Build System entry point
 #
 # This file is evaluated by scons (the build system) every time fbt is invoked.
 # Scons constructs all referenced environments & their targets' dependency
@@ -9,13 +9,14 @@
 import os
 import subprocess
 
+DefaultEnvironment(tools=[])
+
 EnsurePythonVersion(3, 8)
 
-DefaultEnvironment(tools=[])
 # Progress(["OwO\r", "owo\r", "uwu\r", "owo\r"], interval=15)
 
 
-# This environment is created only for loading options & validating file/dir existance
+# This environment is created only for loading options & validating file/dir existence
 fbt_variables = SConscript("site_scons/commandline.scons")
 cmd_environment = Environment(tools=[], variables=fbt_variables)
 Help(fbt_variables.GenerateHelpText(cmd_environment))
@@ -58,6 +59,8 @@ distenv = coreenv.Clone(
         "-ex",
         "source debug/FreeRTOS/FreeRTOS.py",
         "-ex",
+        "source debug/flipperapps.py",
+        "-ex",
         "source debug/PyCortexMDebug/PyCortexMDebug.py",
         "-ex",
         "svd_load ${SVD_FILE}",
@@ -160,6 +163,28 @@ if GetOption("fullenv") or any(
 basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"])
 distenv.Default(basic_dist)
 
+dist_dir = distenv.GetProjetDirName()
+plugin_dist = [
+    distenv.Install(
+        f"#/dist/{dist_dir}/apps/debug_elf",
+        firmware_env["FW_EXTAPPS"]["debug"].values(),
+    ),
+    *(
+        distenv.Install(f"#/dist/{dist_dir}/apps/{dist_entry[0]}", dist_entry[1])
+        for dist_entry in firmware_env["FW_EXTAPPS"]["dist"].values()
+    ),
+]
+Depends(plugin_dist, firmware_env["FW_EXTAPPS"]["validators"].values())
+Alias("plugin_dist", plugin_dist)
+# distenv.Default(plugin_dist)
+
+plugin_resources_dist = list(
+    distenv.Install(f"#/assets/resources/apps/{dist_entry[0]}", dist_entry[1])
+    for dist_entry in firmware_env["FW_EXTAPPS"]["dist"].values()
+)
+distenv.Depends(firmware_env["FW_RESOURCES"], plugin_resources_dist)
+
+
 # Target for bundling core2 package for qFlipper
 copro_dist = distenv.CoproBuilder(
     distenv.Dir("assets/core2_firmware"),
@@ -240,7 +265,6 @@ firmware_env.Append(
         "site_scons",
         "scripts",
         # Extra files
-        "applications/extapps.scons",
         "SConstruct",
         "firmware.scons",
         "fbt_options.py",

+ 71 - 19
applications/ReadMe.md

@@ -1,38 +1,90 @@
 # Structure
 
-- `about`               - Small About application that shows flipper info
-- `accessor`            - Wiegand server
+- `application.h`       - Firmware application list header
+
+
+## debug 
+
+Applications for factory testing the Flipper.
+
+- `accessor`            - Wiegand server 
+- `battery_test_app`    - Battery debug app
+- `blink_test`          - LED blinker   
+- `bt_debug_app`        - BT test app. Requires full BT stack installed
+- `display_test`        - Various display tests & tweaks
+- `file_browser_test`   - Test UI for file picker
+- `keypad_test`         - Keypad test
+- `lfrfid_debug`        - LF RFID debug tool
+- `text_box_test`       - UI tests
+- `uart_echo`           - UART mode test 
+- `unit_tests`          - Unit tests
+- `usb_mouse`           - USB HID test
+- `usb_test`            - Other USB tests
+- `vibro_test`          - Vibro test
+
+
+## main
+
+Applications for main Flipper menu.
+
 - `archive`             - Archive and file manager 
 - `bad_usb`             - Bad USB application
+- `fap_loader`          - External applications loader
+- `gpio`                - GPIO application: includes USART bridge and GPIO control
+- `ibutton`             - iButton application, onewire keys and more
+- `infrared`            - Infrared application, controls your IR devices
+- `lfrfid`              - LF RFID application
+- `nfc`                 - NFC application, HF rfid, EMV and etc
+- `subghz`              - SubGhz application, 433 fobs and etc
+- `u2f`                 - U2F Application
+
+
+## plugins
+
+Extra apps for Plugins & App Loader menus.
+
+- `bt_hid_app`          - BT Remote controller
+- `music_player`        - Music player app (demo)
+- `picopass`            - Picopass tool
+- `snake_game`          - Snake game application
+
+
+## services
+
+Background services providing system APIs to applications.
+
 - `bt`                  - BLE service and application
 - `cli`                 - Console service and API
 - `crypto`              - Crypto cli tools
-- `debug_tools`         - Different tools that we use for debug
 - `desktop`             - Desktop service
 - `dialogs`             - Dialogs service: GUI Dialogs for your app
 - `dolphin`             - Dolphin service and supplementary apps
-- `gpio`                - GPIO application: includes USART bridge and GPIO control
 - `gui`                 - GUI service and API
-- `ibutton`             - iButton application, onewire keys and more
 - `input`               - Input service
-- `infrared`            - Infrared application, controls your IR devices
-- `lfrfid`              - LF RFID application
-- `lfrfid_debug`        - LF RFID debug tool
 - `loader`              - Application loader service
-- `music_player`        - Music player app (demo)
-- `nfc`                 - NFC application, HF rfid, EMV and etc
 - `notification`        - Notification service 
 - `power`               - Power service
-- `power_observer`      - Power debug tool
 - `rpc`                 - RPC service and API
-- `scened_app_example`  - C++ application example
-- `snake_game`          - Snake game application
 - `storage`             - Storage service, internal + sdcard
+
+
+## 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
-- `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
+- `system`              - System settings
 
-- `application.h`       - Firmware application list header
+
+## system
+
+Utility apps not visible in other menus.
+
+- `storage_move_to_sd`  - Data migration tool for internal storage
+- `updater`             - Update service & application

+ 0 - 66
applications/bt/application.fam

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

+ 0 - 0
applications/accessor/accessor.cpp → applications/debug/accessor/accessor.cpp


+ 0 - 0
applications/accessor/accessor_app.cpp → applications/debug/accessor/accessor_app.cpp


+ 0 - 0
applications/accessor/accessor_app.h → applications/debug/accessor/accessor_app.h


+ 0 - 0
applications/accessor/accessor_event.h → applications/debug/accessor/accessor_event.h


+ 0 - 0
applications/accessor/accessor_view_manager.cpp → applications/debug/accessor/accessor_view_manager.cpp


+ 0 - 0
applications/accessor/accessor_view_manager.h → applications/debug/accessor/accessor_view_manager.h


+ 1 - 0
applications/accessor/application.fam → applications/debug/accessor/application.fam

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

+ 0 - 0
applications/accessor/helpers/wiegand.cpp → applications/debug/accessor/helpers/wiegand.cpp


+ 0 - 0
applications/accessor/helpers/wiegand.h → applications/debug/accessor/helpers/wiegand.h


+ 0 - 0
applications/accessor/scene/accessor_scene_generic.h → applications/debug/accessor/scene/accessor_scene_generic.h


+ 0 - 0
applications/accessor/scene/accessor_scene_start.cpp → applications/debug/accessor/scene/accessor_scene_start.cpp


+ 0 - 0
applications/accessor/scene/accessor_scene_start.h → applications/debug/accessor/scene/accessor_scene_start.h


+ 16 - 0
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",
+    ],
+)

+ 14 - 0
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",
+)

+ 5 - 5
applications/power/battery_test_app/battery_test_app.c → 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

+ 3 - 2
applications/power/battery_test_app/battery_test_app.h → applications/debug/battery_test_app/battery_test_app.h

@@ -6,14 +6,15 @@
 #include <notification/notification.h>
 
 #include <gui/modules/dialog_ex.h>
-#include <power/power_settings_app/views/battery_info.h>
+// FIXME
+#include "../settings/power_settings_app/views/battery_info.h"
 
 typedef struct {
     Power* power;
     Gui* gui;
     NotificationApp* notifications;
     ViewDispatcher* view_dispatcher;
-    BatteryInfo* batery_info;
+    BatteryInfo* battery_info;
     DialogEx* dialog;
     PowerInfo info;
 } BatteryTestApp;

+ 11 - 0
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",
+)

+ 0 - 0
applications/debug_tools/blink_test.c → applications/debug/blink_test/blink_test.c


+ 18 - 0
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",
+)

+ 0 - 0
applications/bt/bt_debug_app/bt_debug_app.c → applications/debug/bt_debug_app/bt_debug_app.c


+ 1 - 1
applications/bt/bt_debug_app/bt_debug_app.h → applications/debug/bt_debug_app/bt_debug_app.h

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

+ 0 - 0
applications/bt/bt_debug_app/views/bt_carrier_test.c → applications/debug/bt_debug_app/views/bt_carrier_test.c


+ 0 - 0
applications/bt/bt_debug_app/views/bt_carrier_test.h → applications/debug/bt_debug_app/views/bt_carrier_test.h


+ 0 - 0
applications/bt/bt_debug_app/views/bt_packet_test.c → applications/debug/bt_debug_app/views/bt_packet_test.c


+ 0 - 0
applications/bt/bt_debug_app/views/bt_packet_test.h → applications/debug/bt_debug_app/views/bt_packet_test.h


+ 0 - 0
applications/bt/bt_debug_app/views/bt_test.c → applications/debug/bt_debug_app/views/bt_test.c


+ 0 - 0
applications/bt/bt_debug_app/views/bt_test.h → applications/debug/bt_debug_app/views/bt_test.h


+ 0 - 0
applications/bt/bt_debug_app/views/bt_test_types.h → applications/debug/bt_debug_app/views/bt_test_types.h


+ 11 - 0
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",
+)

+ 0 - 0
applications/debug_tools/display_test/display_test.c → applications/debug/display_test/display_test.c


+ 0 - 0
applications/debug_tools/display_test/display_test.h → applications/debug/display_test/display_test.h


+ 0 - 0
applications/debug_tools/display_test/view_display_test.c → applications/debug/display_test/view_display_test.c


+ 0 - 0
applications/debug_tools/display_test/view_display_test.h → applications/debug/display_test/view_display_test.h


+ 11 - 0
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",
+)

+ 0 - 0
applications/debug_tools/file_browser_test/file_browser_app.c → applications/debug/file_browser_test/file_browser_app.c


+ 0 - 0
applications/debug_tools/file_browser_test/file_browser_app_i.h → applications/debug/file_browser_test/file_browser_app_i.h


+ 0 - 0
applications/debug_tools/file_browser_test/scenes/file_browser_scene.c → applications/debug/file_browser_test/scenes/file_browser_scene.c


+ 0 - 0
applications/debug_tools/file_browser_test/scenes/file_browser_scene.h → applications/debug/file_browser_test/scenes/file_browser_scene.h


+ 0 - 0
applications/debug_tools/file_browser_test/scenes/file_browser_scene_browser.c → applications/debug/file_browser_test/scenes/file_browser_scene_browser.c


+ 0 - 0
applications/debug_tools/file_browser_test/scenes/file_browser_scene_config.h → applications/debug/file_browser_test/scenes/file_browser_scene_config.h


+ 0 - 0
applications/debug_tools/file_browser_test/scenes/file_browser_scene_result.c → applications/debug/file_browser_test/scenes/file_browser_scene_result.c


+ 0 - 0
applications/debug_tools/file_browser_test/scenes/file_browser_scene_start.c → applications/debug/file_browser_test/scenes/file_browser_scene_start.c


+ 11 - 0
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",
+)

+ 0 - 0
applications/debug_tools/keypad_test.c → applications/debug/keypad_test/keypad_test.c


+ 4 - 1
applications/lfrfid_debug/application.fam → 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",
 )

+ 81 - 0
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;
+}

+ 30 - 0
applications/debug/lfrfid_debug/lfrfid_debug_i.h

@@ -0,0 +1,30 @@
+#pragma once
+#include <furi.h>
+#include <furi_hal.h>
+
+#include <gui/gui.h>
+#include <gui/view.h>
+#include <gui/view_dispatcher.h>
+#include <gui/scene_manager.h>
+
+#include <gui/modules/submenu.h>
+
+#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;

+ 44 - 0
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);
+}

+ 17 - 11
applications/lfrfid_debug/scene/lfrfid_debug_app_scene_tune.cpp → 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 <furi_hal.h>
 
 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<LfRfidViewTuneVM>();
+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 consumed = false;
+bool lfrfid_debug_scene_tune_on_event(void* context, SceneManagerEvent event) {
+    UNUSED(event);
 
-    LfRfidViewTuneVM* tune = app->view_controller;
+    LfRfidDebug* app = context;
+    bool consumed = false;
 
-    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);
 

+ 30 - 0
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,
+};

+ 29 - 0
applications/debug/lfrfid_debug/scenes/lfrfid_debug_scene.h

@@ -0,0 +1,29 @@
+#pragma once
+
+#include <gui/scene_manager.h>
+
+// 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

+ 2 - 0
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)

+ 229 - 0
applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.c

@@ -0,0 +1,229 @@
+#include "lfrfid_debug_view_tune.h"
+#include <gui/elements.h>
+
+#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;
+}

+ 18 - 0
applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.h

@@ -0,0 +1,18 @@
+#pragma once
+#include <gui/view.h>
+
+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);

+ 11 - 0
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",
+)

+ 0 - 0
applications/debug_tools/text_box_test.c → applications/debug/text_box_test/text_box_test.c


+ 11 - 0
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",
+)

+ 0 - 0
applications/debug_tools/uart_echo.c → applications/debug/uart_echo/uart_echo.c


+ 1 - 1
applications/unit_tests/application.fam → 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"],

+ 0 - 0
applications/unit_tests/flipper_format/flipper_format_string_test.c → applications/debug/unit_tests/flipper_format/flipper_format_string_test.c


+ 0 - 0
applications/unit_tests/flipper_format/flipper_format_test.c → applications/debug/unit_tests/flipper_format/flipper_format_test.c


+ 0 - 0
applications/unit_tests/furi/furi_memmgr_test.c → applications/debug/unit_tests/furi/furi_memmgr_test.c


+ 0 - 0
applications/unit_tests/furi/furi_pubsub_test.c → applications/debug/unit_tests/furi/furi_pubsub_test.c


+ 0 - 0
applications/unit_tests/furi/furi_record_test.c → applications/debug/unit_tests/furi/furi_record_test.c


+ 0 - 0
applications/unit_tests/furi/furi_test.c → applications/debug/unit_tests/furi/furi_test.c


+ 0 - 0
applications/unit_tests/furi/furi_valuemutex_test.c → applications/debug/unit_tests/furi/furi_valuemutex_test.c


+ 0 - 0
applications/unit_tests/infrared/infrared_test.c → applications/debug/unit_tests/infrared/infrared_test.c


+ 0 - 0
applications/unit_tests/lfrfid/bit_lib_test.c → applications/debug/unit_tests/lfrfid/bit_lib_test.c


+ 0 - 0
applications/unit_tests/lfrfid/lfrfid_protocols.c → applications/debug/unit_tests/lfrfid/lfrfid_protocols.c


+ 0 - 0
applications/unit_tests/minunit.h → applications/debug/unit_tests/minunit.h


+ 0 - 0
applications/unit_tests/minunit_vars.h → applications/debug/unit_tests/minunit_vars.h


+ 0 - 0
applications/unit_tests/minunit_vars_ex.h → applications/debug/unit_tests/minunit_vars_ex.h


+ 1 - 1
applications/unit_tests/nfc/nfc_test.c → applications/debug/unit_tests/nfc/nfc_test.c

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

+ 0 - 0
applications/unit_tests/protocol_dict/protocol_dict_test.c → applications/debug/unit_tests/protocol_dict/protocol_dict_test.c


+ 0 - 0
applications/unit_tests/rpc/rpc_test.c → applications/debug/unit_tests/rpc/rpc_test.c


+ 0 - 0
applications/unit_tests/storage/dirwalk_test.c → applications/debug/unit_tests/storage/dirwalk_test.c


+ 0 - 0
applications/unit_tests/storage/storage_test.c → applications/debug/unit_tests/storage/storage_test.c


+ 0 - 0
applications/unit_tests/stream/stream_test.c → applications/debug/unit_tests/stream/stream_test.c


+ 33 - 2
applications/unit_tests/subghz/subghz_test.c → 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 196
+#define TEST_RANDOM_COUNT_PARSE 232
 #define TEST_TIMEOUT 10000
 
 static SubGhzEnvironment* environment_handler;
@@ -127,7 +127,7 @@ static bool subghz_decode_random_test(const char* path) {
         }
         subghz_file_encoder_worker_free(file_worker_encoder_handler);
     }
-    FURI_LOG_T(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
+    FURI_LOG_D(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
     if(furi_get_tick() - test_start > TEST_TIMEOUT * 10) {
         printf("\033[0;31mRandom test ERROR TimeOut\033[0m\r\n");
         return false;
@@ -419,6 +419,21 @@ MU_TEST(subghz_decoder_magellen_test) {
         "Test decoder " SUBGHZ_PROTOCOL_MAGELLEN_NAME " error\r\n");
 }
 
+MU_TEST(subghz_decoder_intertechno_v3_test) {
+    mu_assert(
+        subghz_decoder_test(
+            EXT_PATH("unit_tests/subghz/intertechno_v3_raw.sub"),
+            SUBGHZ_PROTOCOL_INTERTECHNO_V3_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_INTERTECHNO_V3_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_clemsa_test) {
+    mu_assert(
+        subghz_decoder_test(
+            EXT_PATH("unit_tests/subghz/clemsa_raw.sub"), SUBGHZ_PROTOCOL_CLEMSA_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_CLEMSA_NAME " error\r\n");
+}
+
 //test encoders
 MU_TEST(subghz_encoder_princeton_test) {
     mu_assert(
@@ -528,6 +543,18 @@ MU_TEST(subghz_encoder_magellen_test) {
         "Test encoder " SUBGHZ_PROTOCOL_MAGELLEN_NAME " error\r\n");
 }
 
+MU_TEST(subghz_encoder_intertechno_v3_test) {
+    mu_assert(
+        subghz_encoder_test(EXT_PATH("unit_tests/subghz/intertechno_v3.sub")),
+        "Test encoder " SUBGHZ_PROTOCOL_INTERTECHNO_V3_NAME " error\r\n");
+}
+
+MU_TEST(subghz_encoder_clemsa_test) {
+    mu_assert(
+        subghz_encoder_test(EXT_PATH("unit_tests/subghz/clemsa.sub")),
+        "Test encoder " SUBGHZ_PROTOCOL_CLEMSA_NAME " error\r\n");
+}
+
 MU_TEST(subghz_random_test) {
     mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
 }
@@ -566,6 +593,8 @@ MU_TEST_SUITE(subghz) {
     MU_RUN_TEST(subghz_decoder_phoenix_v2_test);
     MU_RUN_TEST(subghz_decoder_honeywell_wdb_test);
     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_encoder_princeton_test);
     MU_RUN_TEST(subghz_encoder_came_test);
@@ -585,6 +614,8 @@ MU_TEST_SUITE(subghz) {
     MU_RUN_TEST(subghz_encoder_phoenix_v2_test);
     MU_RUN_TEST(subghz_encoder_honeywell_wdb_test);
     MU_RUN_TEST(subghz_encoder_magellen_test);
+    MU_RUN_TEST(subghz_encoder_intertechno_v3_test);
+    MU_RUN_TEST(subghz_encoder_clemsa_test);
 
     MU_RUN_TEST(subghz_random_test);
     subghz_test_deinit();

+ 0 - 0
applications/unit_tests/test_index.c → applications/debug/unit_tests/test_index.c


+ 0 - 0
applications/unit_tests/varint/varint_test.c → applications/debug/unit_tests/varint/varint_test.c


+ 11 - 0
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",
+)

+ 0 - 0
applications/debug_tools/usb_mouse.c → applications/debug/usb_mouse/usb_mouse.c


+ 11 - 0
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",
+)

+ 0 - 0
applications/debug_tools/usb_test.c → applications/debug/usb_test/usb_test.c


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików