Quellcode durchsuchen

Merge subghz_bruteforcer from https://github.com/DarkFlippers/flipperzero-subbrute

Willy-JL vor 2 Jahren
Ursprung
Commit
0d65829ac8

+ 21 - 0
subghz_bruteforcer/.github/release.yml

@@ -0,0 +1,21 @@
+changelog:
+  exclude:
+    labels:
+      - ignore-for-release
+  categories:
+    - title: Breaking Changes 🛠
+      labels:
+        - breaking-change
+    - title: Exciting New Features 🎉
+      labels:
+        - enhancement
+    - title: Bug fixes🧑‍🔧 🐞
+      labels:
+        - bug
+    - title: Doc improvements 📚
+      labels:
+        - docs
+        - documentation
+    - title: Other Changes
+      labels:
+        - "*"

+ 240 - 0
subghz_bruteforcer/.github/workflows/build-with-firmware.yml

@@ -0,0 +1,240 @@
+name: "Build with Firmware"
+run-name: "Build ${{ inputs.DEPLOY_TARGET }} triggered by ${{ github.EVENT_NAME }} (@${{ github.ACTOR }})"
+
+on:
+  workflow_dispatch:
+    inputs:
+      version:
+        description: "Enter version to build or left empty for the NEXT version"
+        required: false
+        type: string
+#  push:
+#    paths:
+#      - .github/workflows/build-with-firmware.yml
+
+permissions:
+  contents: write
+  packages: write
+
+#concurrency:
+#  group: firmware-build-${{ vars.FIRMWARE_VERSION }}-${{ vars.RELEASE_VERSION }}
+#  cancel-in-progress: false
+
+jobs:
+  build-and-upload:
+    runs-on: ubuntu-latest
+    env:
+      REPO_SELF: ${{ vars.REPO_SELF }}
+      APP_PATH: "applications_user/subbrute"
+      RELATIVE_PATH: "applications/external/subbrute"
+      PREV_TAG: ""
+      APP_NAME: ""
+      ZIP_NAME: ""
+      ZIP_TAG: ""
+      TGZ_NAME: ""
+      TGZ_TAG: ""
+      SHA: ""
+      FW_VERSION: ""
+      RELEASE_VERSION: ""
+    strategy:
+      fail-fast: false
+      matrix:
+        firmware: [unlshd, official]
+        include:
+          - firmware: unlshd
+            url: ${{ vars.REPO_UNLEASHED }}
+            version: ${{ vars.FIRMWARE_VERSION }}
+            src-included: 0
+          - firmware: official
+            url: ${{ vars.REPO_OFFICIAL }}
+            version: official
+            src-included: 0
+    steps:
+      - name: Copy Firmware Files
+        uses: actions/checkout@v3
+        with:
+          repository: ${{ matrix.url }}
+          clean: true
+          submodules: true
+          ref: dev
+
+      - name: Copy Repo Files
+        if: ${{ matrix.src-included == 0 }}
+        uses: actions/checkout@v3
+        with:
+          repository: ${{ vars.REPO_SELF }}
+          clean: true
+          submodules: true
+          path: ${{ env.APP_PATH }}
+
+      #    - name: Restore FBT
+      #      id: cache-restore
+      #      if: ${{ success() }}
+      #      uses: actions/cache/restore@v3
+      #      with:
+      #        path: |
+      #          build/**
+      #          debug/**
+      #        # An explicit key for restoring and saving the cache
+      #        key: 'fbt=${{ env.FIRMWARE_VERSION }}'
+      #
+      - name: Remove other apps
+        shell: pwsh
+        # rm to remove problem FAP which includes non-existent files
+        run: |
+          Remove-Item -Force -Recurse ./applications/debug -ErrorAction SilentlyContinue
+          Remove-Item -Force -Recurse ./applications/examples -ErrorAction SilentlyContinue
+          Remove-Item -Force -Recurse ${{ env.RELATIVE_PATH }} -ErrorAction SilentlyContinue
+
+      - name: Get SHA of our application and release version
+        shell: pwsh
+        env:
+          GITHUB_TOKEN: ${{ secrets.FLIPPER_TOKEN }}
+          INPUT_VERSION: ${{ inputs.version }}
+        run: |
+          Write-Output "::notice title=${{ matrix.firmware }} Input Version Number::v${{ inputs.version }}"
+          $fwInfo = ((gh release view --json tagName,url -R ${{ matrix.url }}) | ConvertFrom-Json)
+          cd '${{ env.APP_PATH }}'
+          $sha = (git rev-parse --verify HEAD)
+          
+          $releaseVersion = ''
+          $latestTag = ((gh release view --json tagName,url -R ${{ vars.REPO_SELF }}) | ConvertFrom-Json ).tagName
+
+          if ( [string]::IsNullOrWhitespace($env:INPUT_VERSION) ) {            
+            Write-Output "::notice title=${{ matrix.firmware }} Latest tag::$latestTag"
+            
+            $lastIndex = $latestTag.LastIndexOf('.')
+            
+            $minorValue = $latestTag.Substring($latestTag.LastIndexOf('.') + 1)
+            $minorValue = [Convert]::ToInt32($minorValue) + 1
+            $newTag = $latestTag.Substring(0, $lastIndex)
+            
+            $releaseVersion = ('{0}.{1}' -f $newTag, $minorValue)
+          } else {
+            $releaseVersion = "$env:INPUT_VERSION"
+          }
+          
+          if ( $releaseVersion.StartsWith('v') ) {
+            $releaseVersion = $releaseVersion.Substring(1)
+          }
+          
+          Write-Output "::notice title=${{ matrix.firmware }} PREV_TAG::$latestTag"
+          Write-Output "::notice title=${{ matrix.firmware }} RELEASE_VERSION::$releaseVersion"
+          Write-Output "::notice title=${{ matrix.firmware }} SHA::$sha"
+          Write-Output ('::notice title=${{ matrix.firmware }} FW_VERSION::{0}' -f $fwInfo.tagName)
+          
+          Write-Output ('RELEASE_VERSION={0}' -f $releaseVersion) >> $env:GITHUB_ENV
+          Write-Output ('SHA={0}' -f $sha) >> $env:GITHUB_ENV
+          Write-Output ('FW_VERSION={0}' -f $fwInfo.tagName) >> $env:GITHUB_ENV
+          Write-Output ('PREV_TAG={0}' -f $latestTag) >> $env:GITHUB_ENV
+
+      - name: Build Firmware
+        shell: bash
+        if: ${{ success() }}
+        env:
+          FBT_NO_SYNC: 0
+          DIST_SUFFIX: ${{ matrix.version }}
+          WORKFLOW_BRANCH_OR_TAG: release-cfw
+        run: |
+          ./fbt COMPACT=1 DEBUG=0 FBT_NO_SYNC=0
+
+      - name: Build FAPs
+        shell: bash
+        if: ${{ success() }}
+        env:
+          FBT_NO_SYNC: 0
+          DIST_SUFFIX: ${{ matrix.version }}
+          WORKFLOW_BRANCH_OR_TAG: release-cfw
+          # rm to remove problem FAP which includes non-existent files
+        run: |
+          ./fbt COMPACT=1 DEBUG=0 FBT_NO_SYNC=0 fap_dist
+
+      #    - name: Save FBT
+      #      id: cache-save
+      #      if: ${{ success() }}
+      #      uses: actions/cache/save@v3
+      #      with:
+      #        path: |
+      #          build/**
+      #          debug/**
+      #        # An explicit key for restoring and saving the cache
+      #        key: ${{ steps.cache-restore.outputs.cache-primary-key }}
+
+      - name: Create assets
+        if: ${{ success() }}
+        shell: pwsh
+        env:
+          APP_NAME: "subghz_bruteforcer_${{ env.RELEASE_VERSION }}"
+        run: |
+          function Format-Bytes {
+            param(
+                  [int]$number
+              )
+              $sizes = 'KB', 'MB', 'GB', 'TB', 'PB'
+              for ($x = 0; $x -lt $sizes.count; $x++) {
+                  if ($number -lt [int64]"1$($sizes[$x])") {
+                      if ($x -eq 0) {
+                          return "$number B"
+                      }
+                      else {
+                          $formattedNumber = $number / [int64]"1$($sizes[$x-1])"
+                          $formattedNumber = "{0:N2}" -f $formattedNumber
+                          return "$formattedNumber $($sizes[$x-1])"
+                      }
+                  }
+              }
+          }
+          $appName = $env:APP_NAME
+          if ( '${{ matrix.firmware }}' -eq 'unlshd' ) {
+            $appName = ('{0}_${{ env.FW_VERSION }}' -f $appName)
+          } else {
+            $appName = ('{0}_${{ matrix.firmware}}-${{ env.FW_VERSION }}' -f $appName)
+          }
+          $zipName = ('{0}.zip' -f $appName)
+          $tgzName = ('{0}.tgz' -f $appName)
+          $fapName = 'subghz_bruteforcer.fap'
+          $dstFap = "./$fapName"
+          $appDir = "dist/f7-C/apps/Sub-GHz"
+
+          if (!(Test-Path -Path "$appDir/$fapName" -PathType Leaf)) {
+              Write-Error '::error title=Files not found::Cannot find files in location'
+              exit 1
+          }
+
+          $size = (Get-Item -Path "$appDir/$fapName" | Get-ItemPropertyValue -Name Length)
+          Write-Output ('Filesize: {0}' -f (Format-Bytes $size))
+          Copy-Item -Force -Verbose -Path "$appDir/$fapName" -Destination $dstFap
+
+          zip -r -qq $zipName $dstFap
+          tar zcf $tgzName $dstFap
+
+          if ( !(Test-Path -Path $zipName -PathType Leaf) -or !(Test-Path -Path $tgzName -PathType Leaf) ) {
+              Write-Error '::error title=Files not found::Cannot find files in location'
+              exit 1
+          }
+
+          $zipSize = Format-Bytes (Get-Item -Path $zipName).Length
+          $tgzSize = Format-Bytes (Get-Item -Path $tgzName ).Length
+
+          Write-Output ('ZIP_NAME={0}' -f $zipName) >> $env:GITHUB_ENV
+          Write-Output ('TGZ_NAME={0}' -f $tgzName ) >> $env:GITHUB_ENV
+          Write-Output ('ZIP_TAG={0} ({1})' -f $zipName, $zipSize) >> $env:GITHUB_ENV
+          Write-Output ('TGZ_TAG={0} ({1})' -f $tgzName , $tgzSize) >> $env:GITHUB_ENV
+
+      - name: Upload assets
+        if: ${{ success() && env.ZIP_NAME != '' }}
+        shell: pwsh
+        env:
+          GITHUB_TOKEN: ${{ secrets.FLIPPER_TOKEN }}
+        run: |
+          $mime = "Accept: application/vnd.github+json"
+          $api = "X-GitHub-Api-Version: 2022-11-28"
+          $json = (gh api -H $mime -H $api /repos/${{ github.REPOSITORY }}/releases) | ConvertFrom-Json
+          $tagExists = ($json.GetEnumerator() | Where-Object { $_.tag_name -eq 'v${{ env.RELEASE_VERSION }}' }) -ne $null
+          if ( $tagExists -eq $false ) {
+            gh api --method POST -H $mime -H $api /repos/${{ github.REPOSITORY }}/releases -f tag_name='v${{ env.RELEASE_VERSION }}' -f target_commitish='${{ env.SHA }}' -f name='v${{ env.RELEASE_VERSION }}' -F draft=false -F prerelease=false -F generate_release_notes=true
+          }          
+          gh release upload 'v${{ env.RELEASE_VERSION }}' '${{ env.ZIP_NAME }}#${{ env.ZIP_TAG }}' '${{ env.TGZ_NAME }}#${{ env.TGZ_TAG }}' --clobber -R ${{ env.REPO_SELF }}
+          gh release edit 'v${{ env.RELEASE_VERSION }}' --draft=false -R ${{ env.REPO_SELF }}
+
+#EOF

+ 0 - 251
subghz_bruteforcer/.github/workflows/build-with-firmwware.yml

@@ -1,251 +0,0 @@
-name: "Build for Firmware"
-run-name: "Build ${{ inputs.DEPLOY_TARGET }} by @${{ github.ACTOR }}"
-
-on:
-  workflow_dispatch:
-    inputs:
-      version:
-        description: "Enter version to build or left empty for current version"
-        required: false
-        type: string
-  release:
-    types: [created, prereleased]
-  push:
-    paths:
-      - .github/workflows/build-with-firmware.yml
-
-permissions:
-  contents: write
-  packages: write
-
-concurrency:
-  group: firmware-build-${{ vars.FIRMWARE_VERSION }}-${{ vars.RELEASE_VERSION }}
-  cancel-in-progress: false
-
-jobs:
-  build-and-upload:
-    runs-on: ubuntu-latest
-    env:
-      REPO_SELF: ${{ vars.REPO_SELF }}
-      OFW_PATH: "applications_user/subbrute"
-      RELATIVE_PATH: "applications/external/subbrute"
-      CURRENT_VERSION: ${{ vars.RELEASE_VERSION }}
-      RELEASE_VERSION: ${{ vars.RELEASE_VERSION }}
-      ZIP_NAME: ""
-      ZIP_TAG: ""
-      TGZ_NAME: ""
-      TGZ_TAG: ""
-    strategy:
-      fail-fast: false
-      matrix:
-        firmware: [unlshd, official]
-        include:
-          - firmware: unlshd
-            url: ${{ vars.REPO_UNLEASHED }}
-            version: ${{ vars.FIRMWARE_VERSION }}
-            src-included: 0
-          - firmware: official
-            url: ${{ vars.REPO_OFFICIAL }}
-            version: "official"
-            src-included: 0
-    steps:
-      - name: Set version
-        env:
-          INPUT_VERSION: ${{ inputs.version }}
-          CURRENT_VERSION: ${{ env.CURRENT_VERSION }}
-        shell: pwsh
-        run: |
-          $ReleaseVersion = ([string]::IsNullOrWhitespace($env:INPUT_VERSION) ? $env:CURRENT_VERSION : $env:INPUT_VERSION)
-          Write-Output ('RELEASE_VERSION={0}' -f $ReleaseVersion) >> $env:GITHUB_ENV
-
-      - name: Copy Firmware Files
-        uses: actions/checkout@v3
-        with:
-          repository: "${{ matrix.url }}"
-          clean: "true"
-          submodules: "true"
-          ref: "dev"
-
-      - name: Copy Repo Files
-        if: ${{ matrix.src-included == 0 }}
-        uses: actions/checkout@v3
-        with:
-          repository: "${{ vars.REPO_SELF }}"
-          clean: "true"
-          submodules: "true"
-          path: "${{ env.OFW_PATH }}"
-
-      - name: Print vars about state or repo if Unleashed
-        if: ${{ matrix.src-included == 1 }}
-        shell: pwsh
-        run: |
-          git log --pretty=format:'%s by %C(yellow)%an%Creset (%ad)%n %n%b' --date=local --abbrev-commit --max-count=1
-          git submodule set-branch --branch master '${{ env.RELATIVE_PATH }}'
-          git submodule sync '${{ env.RELATIVE_PATH }}'
-          cd '${{ env.OFW_PATH }}'
-          if ( '${{ env.CURRENT_VERSION }}' -ne '${{ env.RELEASE_VERSION }}' ) {
-            Write-Output '::warning title=Different version::Current version is ${{ env.CURRENT_VERSION }} but we trying to build ${{ env.RELEASE_VERSION }}'
-            git checkout tags/v${{ env.RELEASE_VERSION }} -b tmp-build
-
-            if ( $LASTEXITCODE -ne 0 ) {
-              Write-Error '::error title=Cannot checkout to this version::Error during execution checkout to this tag ${{ env.RELEASE_VERSION }}'
-              exit 1
-            }
-          }
-
-          $Output = (git log --pretty=format:'%s by %C(yellow)%an%Creset (%ad)%n %n%b' --date=local --abbrev-commit --max-count=1)
-
-          if ( $LASTEXITCODE -ne 0 ) {
-            Write-Error '::error title=Invalid checkout::Invalid checkout'
-            exit 1
-          }
-          Write-Output ('::notice title=Git output::{0}' -f $Output)
-
-      - name: Print vars about state or repo if Official
-        if: ${{ matrix.src-included == 0 }}
-        shell: pwsh
-        run: |
-          git log --pretty=format:'%s by %C(yellow)%an%Creset (%ad)%n %n%b' --date=local --abbrev-commit --max-count=1
-          cd '${{ env.OFW_PATH }}'
-
-          if ( '${{ env.CURRENT_VERSION }}' -ne '${{ env.RELEASE_VERSION }}' ) {
-            Write-Output '::warning title=Different version::Current version is ${{ env.CURRENT_VERSION }} but we trying to build ${{ env.RELEASE_VERSION }}'
-            git checkout tags/v${{ env.RELEASE_VERSION }} -b tmp-build
-
-            if ( $LASTEXITCODE -ne 0 ) {
-              Write-Error '::error title=Cannot checkout to this version::Error during execution checkout to this tag ${{ env.RELEASE_VERSION }}'
-              exit 1
-            }
-          } else {
-            $Output = (git log --pretty=format:'%s by %C(yellow)%an%Creset (%ad)%n %n%b' --date=local --abbrev-commit --max-count=1)
-
-            if ( $LASTEXITCODE -ne 0 ) {
-              Write-Error '::error title=Invalid checkout::Invalid checkout'
-              exit 1
-            }
-            Write-Output ('::notice title=Git output::{0}' -f $Output)
-          }
-
-      #    - name: Restore FBT
-      #      id: cache-restore
-      #      if: ${{ success() }}
-      #      uses: actions/cache/restore@v3
-      #      with:
-      #        path: |
-      #          build/**
-      #          debug/**
-      #        # An explicit key for restoring and saving the cache
-      #        key: 'fbt=${{ env.FIRMWARE_VERSION }}'
-      #
-      - name: Remove other apps
-        shell: pwsh
-        if: ${{ success() }}
-        # rm to remove problem FAP which includes non-existent files
-        run: |
-          Remove-Item -Force -Recurse ./applications/debug -ErrorAction SilentlyContinue
-          Remove-Item -Force -Recurse ./applications/examples -ErrorAction SilentlyContinue
-      #          New-Item -Force ./tmp -ItemType Directory -ErrorAction SilentlyContinue
-      #          Copy-Item -Force -Recurse ./applications/external/subbrute/ ./tmp/ -ErrorAction SilentlyContinue
-      #          Remove-Item -Force -Recurse ./applications/external/* -ErrorAction SilentlyContinue
-      #          Copy-Item -Force -Recurse /tmp/* ./applications/external/ -ErrorAction SilentlyContinue
-      #          Remove-Item -Force -Recurse ./tmp -ErrorAction SilentlyContinue
-
-      - name: Build Firmware
-        shell: bash
-        if: ${{ success() }}
-        env:
-          FBT_NO_SYNC: 0
-          DIST_SUFFIX: ${{ matrix.version }}
-          WORKFLOW_BRANCH_OR_TAG: release-cfw
-        run: |
-          ./fbt COMPACT=1 DEBUG=0 FBT_NO_SYNC=0
-
-      - name: Build FAPs
-        shell: bash
-        if: ${{ success() }}
-        env:
-          FBT_NO_SYNC: 0
-          DIST_SUFFIX: ${{ matrix.version }}
-          WORKFLOW_BRANCH_OR_TAG: release-cfw
-          # rm to remove problem FAP which includes non-existent files
-        run: |
-          ./fbt COMPACT=1 DEBUG=0 FBT_NO_SYNC=0 fap_dist
-
-      #    - name: Save FBT
-      #      id: cache-save
-      #      if: ${{ success() }}
-      #      uses: actions/cache/save@v3
-      #      with:
-      #        path: |
-      #          build/**
-      #          debug/**
-      #        # An explicit key for restoring and saving the cache
-      #        key: ${{ steps.cache-restore.outputs.cache-primary-key }}
-
-      - name: Create assets
-        if: ${{ success() }}
-        shell: pwsh
-        env:
-          ZIP_NAME: "subghz_bruteforcer_${{ env.RELEASE_VERSION }}_${{ matrix.firmware }}.zip"
-          TGZ_NAME: "subghz_bruteforcer_${{ env.RELEASE_VERSION }}_${{ matrix.firmware }}.tgz"
-        run: |
-          function Format-Bytes {
-            param(
-                  [int]$number
-              )
-              $sizes = 'KB', 'MB', 'GB', 'TB', 'PB'
-              for ($x = 0; $x -lt $sizes.count; $x++) {
-                  if ($number -lt [int64]"1$($sizes[$x])") {
-                      if ($x -eq 0) {
-                          return "$number B"
-                      }
-                      else {
-                          $num = $number / [int64]"1$($sizes[$x-1])"
-                          $num = "{0:N2}" -f $num
-                          return "$num $($sizes[$x-1])"
-                      }
-                  }
-              }
-          }
-          $ZipName = $env:ZIP_NAME
-          $TgzName = $env:TGZ_NAME
-          $FapNamme = 'subghz_bruteforcer.fap'
-          $DstFap = "./$FapNamme"
-          $AppDir = "dist/f7-C/apps/Sub-GHz"
-
-          if (!(Test-Path -Path "$AppDir/$FapNamme" -PathType Leaf)) {
-              Write-Error '::error title=Files not found::Cannot find files in location'
-              exit 1
-          }
-
-          $Size = (Get-Item -Path "$AppDir/$FapNamme" | Get-ItemPropertyValue -Name Length)
-          Write-Output ('Filesize: {0}' -f (Format-Bytes $Size))
-          Copy-Item -Force -Verbose -Path "$AppDir/$FapNamme" -Destination $DstFap
-
-          zip -r -qq $ZipName $DstFap
-          tar zcf $TgzName $DstFap
-
-          if ( !(Test-Path -Path $ZipName -PathType Leaf) -or !(Test-Path -Path $TgzName -PathType Leaf) ) {
-              Write-Error '::error title=Files not found::Cannot find files in location'
-              exit 1
-          }
-
-          $ZipSize = Format-Bytes (Get-Item -Path $ZipName).Length
-          $TgzSize = Format-Bytes (Get-Item -Path $TgzName ).Length
-
-          Write-Output ('ZIP_NAME={0}' -f $ZipName) >> $env:GITHUB_ENV
-          Write-Output ('TGZ_NAME={0}' -f $TgzName ) >> $env:GITHUB_ENV
-          Write-Output ('ZIP_TAG={0} ({1})' -f $ZipName, $ZipSize) >> $env:GITHUB_ENV
-          Write-Output ('TGZ_TAG={0} ({1})' -f $TgzName , $TgzSize) >> $env:GITHUB_ENV
-
-      - name: Upload assets
-        if: ${{ success() && env.ZIP_NAME != '' }}
-        env:
-          GITHUB_TOKEN: ${{ secrets.FLIPPER_TOKEN }}
-        run: |
-          gh release create v${{ env.RELEASE_VERSION }} --generate-notes --draft -R ${{ env.REPO_SELF }}
-          gh release upload 'v${{ env.RELEASE_VERSION }}' '${{ env.ZIP_NAME }}#${{ env.ZIP_TAG }}' \
-            '${{ env.TGZ_NAME }}#${{ env.TGZ_TAG }}' --clobber -R ${{ env.REPO_SELF }}
-          gh release edit 'v${{ env.RELEASE_VERSION }}' --draft=false -R ${{ env.REPO_SELF }}
-
-#EOF

+ 11 - 10
subghz_bruteforcer/.github/workflows/changelog.yml

@@ -34,17 +34,18 @@ jobs:
           output: CHANGELOG.md
           unreleased: false
           stripGeneratorNotice: true
+          verbose: true
 
       - name: "Show CHANGELOG.md"
         run: cat CHANGELOG.md
 
-      - name: "Commit changes"
-        uses: stefanzweifel/git-auto-commit-action@v4
-        with:
-          commit_message: "docs: update `CHANGELOG.md`"
-          file_pattern: "*.md"
-          branch: ${{ github.ref_name }}
-          commit_options: '--no-verify --signoff'
-          # skip_dirty_check: true
-          # skip_checkout: true
-          # skip_fetch: true
+#      - name: "Commit changes"
+#        uses: stefanzweifel/git-auto-commit-action@v4
+#        with:
+#          commit_message: "docs: update `CHANGELOG.md`"
+#          file_pattern: "*.md"
+#          branch: ${{ github.ref_name }}
+#          commit_options: '--no-verify --signoff'
+#          # skip_dirty_check: true
+#          # skip_checkout: true
+#          # skip_fetch: true

+ 4 - 4
subghz_bruteforcer/.github/workflows/codeql.yml

@@ -12,11 +12,11 @@
 name: "CodeQL"
 
 on:
-  push:
-    branches: ["master", "feat/ci"]
-  pull_request:
+#  push:
+#    branches: ["master", "feat/ci"]
+#  pull_request:
     # The branches below must be a subset of the branches above
-    branches: ["master"]
+#    branches: ["master"]
   schedule:
     - cron: "43 14 * * *"
   workflow_dispatch:

+ 21 - 0
subghz_bruteforcer/.github/workflows/stale.yml

@@ -0,0 +1,21 @@
+name: "Close stale issues and PRs"
+on:
+  schedule:
+    - cron: "* 0 * * *"
+
+jobs:
+  stale:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/stale@v8
+        with:
+          days-before-stale: -1
+          days-before-close: -1
+          stale-pr-message: "This pull request is stale because it has been open 14 days with no activity. To keep this pull request open remove stale label or comment."
+          stale-pr-label: "status:stale"
+          close-pr-message: "This pull request was closed because it has been stale for 14 days with no activity. If this pull request is important or you have more to add feel free to re-open it."
+          days-before-pr-stale: 14
+          days-before-pr-close: 14
+          exempt-issue-labels: "needs:attention,needs:triage,blocked"
+          ascending: true # https://github.com/actions/stale#ascending
+          operations-per-run: 500

+ 153 - 13
subghz_bruteforcer/CHANGELOG.md

@@ -1,5 +1,148 @@
 # Changelog
 
+## [v3.10.1](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.10.1) (2023-12-19)
+
+[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.9.5...v3.10.1)
+
+## [v3.9.5](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.9.5) (2023-12-19)
+
+[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.8.2...v3.9.5)
+
+**Implemented enhancements:**
+
+- Update codeql.yml and disable on push events [\#57](https://github.com/DarkFlippers/flipperzero-subbrute/pull/57) ([derskythe](https://github.com/derskythe))
+- Modify GitHub workflow to generate releases [\#53](https://github.com/DarkFlippers/flipperzero-subbrute/pull/53) ([derskythe](https://github.com/derskythe))
+- Why it say Preload failed API version mismatch? Pls help! I'm using latest release here. [\#21](https://github.com/DarkFlippers/flipperzero-subbrute/issues/21)
+
+
+**Fixed bugs:**
+
+- fix: Improve formatting of subbrute\_protocol\_calc\_max\_value declaration [\#58](https://github.com/DarkFlippers/flipperzero-subbrute/pull/58) ([derskythe](https://github.com/derskythe))
+- fix: invalid calls [\#45](https://github.com/DarkFlippers/flipperzero-subbrute/pull/45) ([derskythe](https://github.com/derskythe))
+- fix: matrix building [\#44](https://github.com/DarkFlippers/flipperzero-subbrute/pull/44) ([derskythe](https://github.com/derskythe))
+- fix: animation in attack mode [\#43](https://github.com/DarkFlippers/flipperzero-subbrute/pull/43) ([derskythe](https://github.com/derskythe))
+- Chamberlain 8 bit code drops bit 3 [\#2](https://github.com/DarkFlippers/flipperzero-subbrute/issues/2)
+
+**Merged pull requests:**
+
+- Merge pull request \#51 from DarkFlippers/master \#59] ([derskythe](https://github.com/derskythe))
+- docs: Add extensive documentation in code comments \#56 ([derskythe](https://github.com/derskythe))
+- Sync [\#51](https://github.com/DarkFlippers/flipperzero-subbrute/pull/51) ([derskythe](https://github.com/derskythe))
+- Add workflow to automatically close stale issues and PRs [\#54](https://github.com/DarkFlippers/flipperzero-subbrute/pull/54) ([derskythe](https://github.com/derskythe))
+- CI/CD fixes [\#52](https://github.com/DarkFlippers/flipperzero-subbrute/pull/52) ([derskythe](https://github.com/derskythe))
+- Update CHANGELOG.md [\#48](https://github.com/DarkFlippers/flipperzero-subbrute/pull/48) ([derskythe](https://github.com/derskythe))
+- Feat/ci changelog [\#46](https://github.com/DarkFlippers/flipperzero-subbrute/pull/46) ([derskythe](https://github.com/derskythe))
+- Minor fixes [\#40](https://github.com/DarkFlippers/flipperzero-subbrute/pull/40) ([gid9798](https://github.com/gid9798))
+- Update docs [\#39](https://github.com/DarkFlippers/flipperzero-subbrute/pull/39) ([derskythe](https://github.com/derskythe))
+- Feat/save settings [\#38](https://github.com/DarkFlippers/flipperzero-subbrute/pull/38) ([derskythe](https://github.com/derskythe))
+- Feat/codeql [\#37](https://github.com/DarkFlippers/flipperzero-subbrute/pull/37) ([derskythe](https://github.com/derskythe))
+- Create codeql.yml [\#36](https://github.com/DarkFlippers/flipperzero-subbrute/pull/36) ([derskythe](https://github.com/derskythe))
+- Sync from master [\#35](https://github.com/DarkFlippers/flipperzero-subbrute/pull/35) ([derskythe](https://github.com/derskythe))
+- Sync [\#27](https://github.com/DarkFlippers/flipperzero-subbrute/pull/27) ([derskythe](https://github.com/derskythe))
+- Sync branch [\#24](https://github.com/DarkFlippers/flipperzero-subbrute/pull/24) ([derskythe](https://github.com/derskythe))
+- Sync working tree [\#11](https://github.com/DarkFlippers/flipperzero-subbrute/pull/11) ([derskythe](https://github.com/derskythe))
+
+**Closed issues:**
+
+- setting file [\#42](https://github.com/DarkFlippers/flipperzero-subbrute/issues/42)
+- Not able to change the number of repetitions per code sent [\#7](https://github.com/DarkFlippers/flipperzero-subbrute/issues/7)
+
+
+**Fixed bugs:**
+
+- Fix 49 [\#50](https://github.com/DarkFlippers/flipperzero-subbrute/pull/50) ([derskythe](https://github.com/derskythe))
+
+**Merged pull requests:**
+
+- Sync [\#61](https://github.com/DarkFlippers/flipperzero-subbrute/pull/61) ([derskythe](https://github.com/derskythe))
+- Sync [\#55](https://github.com/DarkFlippers/flipperzero-subbrute/pull/55) ([derskythe](https://github.com/derskythe))
+
+## [v3.9.5](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.9.5) (2023-12-19)
+
+[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.9.4...v3.9.5)
+
+## [v3.9.5](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.9.5) (2023-12-19)
+
+[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.8.2...v3.9.5)
+
+**Implemented enhancements:**
+
+- Update codeql.yml and disable on push events [\#57](https://github.com/DarkFlippers/flipperzero-subbrute/pull/57) ([derskythe](https://github.com/derskythe))
+- Modify GitHub workflow to generate releases [\#53](https://github.com/DarkFlippers/flipperzero-subbrute/pull/53) ([derskythe](https://github.com/derskythe))
+- Why it say Preload failed API version mismatch? Pls help! I'm using latest release here. [\#21](https://github.com/DarkFlippers/flipperzero-subbrute/issues/21)
+
+
+**Fixed bugs:**
+
+- fix: Improve formatting of subbrute\_protocol\_calc\_max\_value declaration [\#58](https://github.com/DarkFlippers/flipperzero-subbrute/pull/58) ([derskythe](https://github.com/derskythe))
+- fix: invalid calls [\#45](https://github.com/DarkFlippers/flipperzero-subbrute/pull/45) ([derskythe](https://github.com/derskythe))
+- fix: matrix building [\#44](https://github.com/DarkFlippers/flipperzero-subbrute/pull/44) ([derskythe](https://github.com/derskythe))
+- fix: animation in attack mode [\#43](https://github.com/DarkFlippers/flipperzero-subbrute/pull/43) ([derskythe](https://github.com/derskythe))
+- Chamberlain 8 bit code drops bit 3 [\#2](https://github.com/DarkFlippers/flipperzero-subbrute/issues/2)
+
+**Merged pull requests:**
+
+- Merge pull request \#51 from DarkFlippers/master \#59] ([derskythe](https://github.com/derskythe))
+- docs: Add extensive documentation in code comments \#56 ([derskythe](https://github.com/derskythe))
+- Sync [\#51](https://github.com/DarkFlippers/flipperzero-subbrute/pull/51) ([derskythe](https://github.com/derskythe))
+- Add workflow to automatically close stale issues and PRs [\#54](https://github.com/DarkFlippers/flipperzero-subbrute/pull/54) ([derskythe](https://github.com/derskythe))
+- CI/CD fixes [\#52](https://github.com/DarkFlippers/flipperzero-subbrute/pull/52) ([derskythe](https://github.com/derskythe))
+- Update CHANGELOG.md [\#48](https://github.com/DarkFlippers/flipperzero-subbrute/pull/48) ([derskythe](https://github.com/derskythe))
+- Feat/ci changelog [\#46](https://github.com/DarkFlippers/flipperzero-subbrute/pull/46) ([derskythe](https://github.com/derskythe))
+- Minor fixes [\#40](https://github.com/DarkFlippers/flipperzero-subbrute/pull/40) ([gid9798](https://github.com/gid9798))
+- Update docs [\#39](https://github.com/DarkFlippers/flipperzero-subbrute/pull/39) ([derskythe](https://github.com/derskythe))
+- Feat/save settings [\#38](https://github.com/DarkFlippers/flipperzero-subbrute/pull/38) ([derskythe](https://github.com/derskythe))
+- Feat/codeql [\#37](https://github.com/DarkFlippers/flipperzero-subbrute/pull/37) ([derskythe](https://github.com/derskythe))
+- Create codeql.yml [\#36](https://github.com/DarkFlippers/flipperzero-subbrute/pull/36) ([derskythe](https://github.com/derskythe))
+- Sync from master [\#35](https://github.com/DarkFlippers/flipperzero-subbrute/pull/35) ([derskythe](https://github.com/derskythe))
+- Sync [\#27](https://github.com/DarkFlippers/flipperzero-subbrute/pull/27) ([derskythe](https://github.com/derskythe))
+- Sync branch [\#24](https://github.com/DarkFlippers/flipperzero-subbrute/pull/24) ([derskythe](https://github.com/derskythe))
+- Sync working tree [\#11](https://github.com/DarkFlippers/flipperzero-subbrute/pull/11) ([derskythe](https://github.com/derskythe))
+
+**Closed issues:**
+
+- setting file [\#42](https://github.com/DarkFlippers/flipperzero-subbrute/issues/42)
+- Not able to change the number of repetitions per code sent [\#7](https://github.com/DarkFlippers/flipperzero-subbrute/issues/7)
+
+
+**Implemented enhancements:**
+
+- Update codeql.yml and disable on push events [\#57](https://github.com/DarkFlippers/flipperzero-subbrute/pull/57) ([derskythe](https://github.com/derskythe))
+
+**Fixed bugs:**
+
+- fix: Improve formatting of subbrute\_protocol\_calc\_max\_value declaration [\#58](https://github.com/DarkFlippers/flipperzero-subbrute/pull/58) ([derskythe](https://github.com/derskythe))
+
+**Merged pull requests:**
+
+- Merge pull request \#51 from DarkFlippers/master [\#59](https://github.com/DarkFlippers/flipperzero-subbrute/pull/59) ([derskythe](https://github.com/derskythe))
+- docs: Add extensive documentation in code comments [\#56](https://github.com/DarkFlippers/flipperzero-subbrute/pull/56) ([derskythe](https://github.com/derskythe))
+- Sync [\#51](https://github.com/DarkFlippers/flipperzero-subbrute/pull/51) ([derskythe](https://github.com/derskythe))
+
+## [v3.9.4](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.9.4) (2023-12-19)
+
+[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.9.3...v3.9.4)
+
+**Merged pull requests:**
+
+- Add workflow to automatically close stale issues and PRs [\#54](https://github.com/DarkFlippers/flipperzero-subbrute/pull/54) ([derskythe](https://github.com/derskythe))
+
+## [v3.9.3](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.9.3) (2023-12-19)
+
+[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.10.0...v3.9.3)
+
+**Implemented enhancements:**
+
+- Modify GitHub workflow to generate releases [\#53](https://github.com/DarkFlippers/flipperzero-subbrute/pull/53) ([derskythe](https://github.com/derskythe))
+
+**Merged pull requests:**
+
+- CI/CD fixes [\#52](https://github.com/DarkFlippers/flipperzero-subbrute/pull/52) ([derskythe](https://github.com/derskythe))
+
+## [v3.10.0](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.10.0) (2023-11-04)
+
+[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.9.2...v3.10.0)
+
 ## [v3.9.2](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.9.2) (2023-11-04)
 
 [Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.9.1...v3.9.2)
@@ -37,7 +180,7 @@
 
 ## [v3.9.0](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.9.0) (2023-08-27)
 
-[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.8.2...v3.9.0)
+[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.8.1...v3.9.0)
 
 **Fixed bugs:**
 
@@ -57,13 +200,13 @@
 - Sync branch [\#24](https://github.com/DarkFlippers/flipperzero-subbrute/pull/24) ([derskythe](https://github.com/derskythe))
 - Sync working tree [\#11](https://github.com/DarkFlippers/flipperzero-subbrute/pull/11) ([derskythe](https://github.com/derskythe))
 
-## [v3.8.2](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.8.2) (2023-08-25)
+## [v3.8.1](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.8.1) (2023-08-25)
 
-[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.8.1...v3.8.2)
+[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.8.2...v3.8.1)
 
-## [v3.8.1](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.8.1) (2023-08-25)
+## [v3.8.2](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.8.2) (2023-08-25)
 
-[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.8.0...v3.8.1)
+[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.8.0...v3.8.2)
 
 **Merged pull requests:**
 
@@ -79,7 +222,7 @@
 
 ## [v3.7.0](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.7.0) (2023-08-25)
 
-[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.6.0...v3.7.0)
+[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.2.4...v3.7.0)
 
 **Closed issues:**
 
@@ -95,13 +238,13 @@
 - Feat/ci [\#26](https://github.com/DarkFlippers/flipperzero-subbrute/pull/26) ([derskythe](https://github.com/derskythe))
 - Sync [\#25](https://github.com/DarkFlippers/flipperzero-subbrute/pull/25) ([derskythe](https://github.com/derskythe))
 
-## [v3.6.0](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.6.0) (2023-06-09)
+## [v3.2.4](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.2.4) (2023-06-09)
 
-[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.2.4...v3.6.0)
+[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.6.0...v3.2.4)
 
-## [v3.2.4](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.2.4) (2023-06-09)
+## [v3.6.0](https://github.com/DarkFlippers/flipperzero-subbrute/tree/v3.6.0) (2023-06-09)
 
-[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.2.2...v3.2.4)
+[Full Changelog](https://github.com/DarkFlippers/flipperzero-subbrute/compare/v3.2.2...v3.6.0)
 
 **Closed issues:**
 
@@ -151,6 +294,3 @@
 - add honeywell protocol [\#4](https://github.com/DarkFlippers/flipperzero-subbrute/pull/4) ([s0u7f1r3](https://github.com/s0u7f1r3))
 - Feat/existing file two bytes [\#3](https://github.com/DarkFlippers/flipperzero-subbrute/pull/3) ([derskythe](https://github.com/derskythe))
 - Feat/more repeats [\#1](https://github.com/DarkFlippers/flipperzero-subbrute/pull/1) ([derskythe](https://github.com/derskythe))
-
-
-

+ 4 - 4
subghz_bruteforcer/README.md

@@ -19,7 +19,7 @@ You just need to install the [latest firmware](https://github.com/DarkFlippers/u
 <br />
 You can also download the [release](https://github.com/derskythe/flipperzero-subbrute/releases/latest) and unzip/untar it to the `SD Card/apps/Sub-GHz` directory.
 <br />
-> **Warning**
+> [!WARNING]
 > 
 > The application is not compatible with the official firmware version.
 > Also, it has not been tested on other firmware versions other than [Unleashed Firmware](https://github.com/DarkFlippers/unleashed-firmware) and [OFW](https://github.com/flipperdevices/flipperzero-firmware).
@@ -104,7 +104,7 @@ The negative side of increasing the number of repetitions will be a longer key f
 
 ### UNILARM
 
-> **Note**
+> [!NOTE]
 > 
 > Only dip switch combinations, not full 25bit bruteforce
 
@@ -113,7 +113,7 @@ The negative side of increasing the number of repetitions will be a longer key f
 
 ### SMC5326
 
-> **Note**
+> [!NOTE]
 > 
 > Only dip switch combinations, not full 25bit bruteforce
 
@@ -122,7 +122,7 @@ The negative side of increasing the number of repetitions will be a longer key f
 
 ### PT2260
 
-> **Note**
+> [!NOTE]
 > 
 > Only for 8 dip switch remote, not full 24bit bruteforce
 

+ 26 - 1
subghz_bruteforcer/helpers/subbrute_radio_device_loader.h

@@ -2,14 +2,39 @@
 
 #include <lib/subghz/devices/devices.h>
 
-/** SubGhzRadioDeviceType */
+/**
+ * @file subghz_radio.h
+ * @brief Defines the Sub-GHz radio device type.
+ */
 typedef enum {
     SubGhzRadioDeviceTypeInternal,
     SubGhzRadioDeviceTypeExternalCC1101,
 } SubGhzRadioDeviceType;
 
+/**
+ * @brief Sets the SubGhz radio device type.
+ *
+ * This function is used to set the SubGhz radio device type for the SubBrute radio device loader.
+ *
+ * @param current_radio_device Pointer to the current SubGhz radio device.
+ * @param radio_device_type The desired SubGhz radio device type.
+ * @return const SubGhzDevice* Pointer to the new SubGhz radio device.
+ *
+ * @remark This function sets the SubGhz radio device type for the SubBrute radio device loader.
+ *         The current radio device will be replaced with a new instance of the specified radio device type.
+ *         If @p current_radio_device is NULL, a new instance of the specified radio device type will be created.
+ *
+ * @note The caller is responsible for handling memory deallocation of the returned pointer.
+ */
 const SubGhzDevice* subbrute_radio_device_loader_set(
     const SubGhzDevice* current_radio_device,
     SubGhzRadioDeviceType radio_device_type);
 
+/**
+ * @brief Unloads a SubGhz radio device.
+ *
+ * This function unloads a SubGhz radio device and performs any necessary cleanup.
+ *
+ * @param radio_device Pointer to the SubGhzDevice structure representing the radio device to be unloaded.
+ */
 void subbrute_radio_device_loader_end(const SubGhzDevice* radio_device);

+ 220 - 0
subghz_bruteforcer/helpers/subbrute_worker.h

@@ -3,6 +3,18 @@
 #include "../subbrute_protocols.h"
 #include "subbrute_radio_device_loader.h"
 
+/**
+ * @enum SubBruteWorkerState
+ * @brief Enumeration defining the different states of the SubBruteWorker.
+ *
+ * This enumeration defines the possible states of the SubBruteWorker, which is responsible for performing
+ * sub-brute forcing tasks.
+ *
+ * @var SubBruteWorkerStateIDLE The worker is in idle state and not performing any task.
+ * @var SubBruteWorkerStateReady The worker is ready to start a new task.
+ * @var SubBruteWorkerStateTx The worker is currently performing a sub-brute forcing task.
+ * @var SubBruteWorkerStateFinished The worker has finished the sub-brute forcing task.
+ */
 typedef enum {
     SubBruteWorkerStateIDLE,
     SubBruteWorkerStateReady,
@@ -14,17 +26,94 @@ typedef void (*SubBruteWorkerCallback)(void* context, SubBruteWorkerState state)
 
 typedef struct SubBruteWorker SubBruteWorker;
 
+/**
+ * @brief Allocates memory for a SubBruteWorker object and initializes it with the given radio_device.
+ *
+ * This function creates a new SubBruteWorker object by allocating memory for it on the heap and
+ * initializes it with the provided radio_device. The radio_device parameter must not be NULL.
+ *
+ * @param radio_device A pointer to a valid SubGhzDevice object.
+ * @return A pointer to the newly allocated SubBruteWorker object, or NULL if memory allocation failed.
+ */
 SubBruteWorker* subbrute_worker_alloc(const SubGhzDevice* radio_device);
+
+/**
+ * @brief Frees the memory associated with the given SubBruteWorker instance.
+ *
+ * This function must be called to release the resources allocated to the SubBruteWorker instance.
+ *
+ * @param instance Pointer to the SubBruteWorker instance to be freed.
+ */
 void subbrute_worker_free(SubBruteWorker* instance);
+
+/**
+ * @brief Get the current step of a sub brute force worker.
+ *
+ * @param instance A pointer to the SubBruteWorker instance.
+ * @return The current step of the sub brute force worker as a uint64_t value.
+ */
 uint64_t subbrute_worker_get_step(SubBruteWorker* instance);
+
+/**
+ * @brief Set the step value for a SubBruteWorker instance.
+ *
+ * This function sets the step value for a given SubBruteWorker instance. The step value determines the increment that
+ * will be used for each iteration in the worker's execution loop.
+ *
+ * @param instance Pointer to the SubBruteWorker instance.
+ * @param step The step value to set.
+ * @return true if the step value was successfully set, false otherwise.
+ */
 bool subbrute_worker_set_step(SubBruteWorker* instance, uint64_t step);
+
+/**
+ * @brief Check if the SubBruteWorker is currently running.
+ *
+ * @param instance Pointer to the SubBruteWorker instance.
+ *
+ * @return true if the SubBruteWorker is running, false otherwise.
+ */
 bool subbrute_worker_is_running(SubBruteWorker* instance);
+
+/**
+ * @brief Initializes a SubBruteWorker with default attack settings.
+ *
+ * This function initializes a SubBruteWorker instance with default attack settings. The attack_type parameter determines the type of attack to be performed. The step parameter specifies
+* the iteration step to be used during the attack. The protocol parameter provides the necessary protocol information for the attack. The repeats parameter specifies the number of times
+* the attack should be repeated.
+ *
+ * @param instance A pointer to a SubBruteWorker instance.
+ * @param attack_type The type of attack to be performed.
+ * @param step The iteration step to be used during the attack.
+ * @param protocol A pointer to the SubBruteProtocol structure containing protocol information.
+ * @param repeats The number of times the attack should be repeated.
+ * @return Returns true if the initialization is successful, false otherwise.
+ */
 bool subbrute_worker_init_default_attack(
     SubBruteWorker* instance,
     SubBruteAttacks attack_type,
     uint64_t step,
     const SubBruteProtocol* protocol,
     uint8_t repeats);
+
+/**
+ * @brief Initializes a file-based attack worker for the sub-brute algorithm.
+ *
+ * This function initializes a sub-brute worker to perform file-based attacks.
+ * It sets the necessary parameters for the attack, such as the attack step,
+ * the load index, the file key, the protocol to use, the number of repeats,
+ * and whether to use two bytes.
+ *
+ * @param instance A pointer to the sub-brute worker instance.
+ * @param step The attack step value to set.
+ * @param load_index The load index value to set.
+ * @param file_key The file key value to set.
+ * @param protocol The sub-brute protocol to use for the attack.
+ * @param repeats The number of times to repeat the attack.
+ * @param two_bytes A flag indicating whether to use two bytes for the attack.
+ *
+ * @return True if the initialization was successful, false otherwise.
+ */
 bool subbrute_worker_init_file_attack(
     SubBruteWorker* instance,
     uint64_t step,
@@ -33,24 +122,155 @@ bool subbrute_worker_init_file_attack(
     SubBruteProtocol* protocol,
     uint8_t repeats,
     bool two_bytes);
+
+/**
+ * @brief Start the SubBruteWorker instance.
+ *
+ * This function starts the SubBruteWorker instance, allowing it to begin its work.
+ *
+ * @param instance Pointer to the SubBruteWorker instance to start.
+ * @return Whether starting the SubBruteWorker instance was successful.
+ *     - true: Starting the SubBruteWorker instance was successful.
+ *     - false: Starting the SubBruteWorker instance failed.
+ *
+ * @note Before calling this function, make sure all the necessary inputs and configurations
+ *       have been set on the SubBruteWorker instance.
+ */
 bool subbrute_worker_start(SubBruteWorker* instance);
+
+/**
+ * @brief Stops the given SubBruteWorker instance.
+ *
+ * This function stops the SubBruteWorker instance by performing necessary clean-up operations.
+ * After calling this function, the instance is no longer usable.
+ *
+ * @param instance A pointer to the SubBruteWorker instance to stop.
+ */
 void subbrute_worker_stop(SubBruteWorker* instance);
+
+/**
+ * @brief Transmits the current key of the SubBruteWorker instance to another device.
+ *
+ * This function transmits the current key of the SubBruteWorker instance to another device
+ * using the specified step value.
+ *
+ * @param instance The pointer to the SubBruteWorker instance.
+ * @param step The step value used for transmission.
+ *
+ * @return True if the key was successfully transmitted, otherwise false.
+ */
 bool subbrute_worker_transmit_current_key(SubBruteWorker* instance, uint64_t step);
+
+/**
+ * @brief Check if the `SubBruteWorker` instance can transmit manually.
+ *
+ * This function is used to determine if the `SubBruteWorker` instance is capable of manual transmission.
+ *
+ * @param instance Pointer to the `SubBruteWorker` instance.
+ * @return `true` if the `SubBruteWorker` instance can transmit manually, `false` otherwise.
+ */
 bool subbrute_worker_can_manual_transmit(SubBruteWorker* instance);
+
+/**
+ * @brief Set the callback function and its context for the SubBruteWorker.
+ *
+ * This function allows you to set the callback function and its context for
+ * the given SubBruteWorker instance. The callback function will be called
+ * by the SubBruteWorker at specific events, providing information to the
+ * caller through the callback parameters.
+ *
+ * @param instance The SubBruteWorker instance to set the callback for.
+ * @param callback The callback function to set.
+ * @param context The context to be passed to the callback function.
+ *
+ * @note The callback function should be of the form:
+ *        void callback(SubBruteWorker* instance, void* context);
+ *      The instance parameter is the SubBruteWorker instance that triggered
+ *      the callback, while the context parameter is the user-defined context
+ *      that was set with this function.
+ *
+ * @see SubBruteWorkerCallback
+ */
 void subbrute_worker_set_callback(
     SubBruteWorker* instance,
     SubBruteWorkerCallback callback,
     void* context);
 
+/**
+ * @brief Get the timeout value of the SubBruteWorker instance.
+ *
+ * This function returns the timeout value of the SubBruteWorker instance.
+ *
+ * @param instance  Pointer to the SubBruteWorker instance.
+ *
+ * @return The timeout value as a uint8_t.
+ */
 uint8_t subbrute_worker_get_timeout(SubBruteWorker* instance);
+
+/**
+ * @brief Set the timeout for the SubBruteWorker instance.
+ *
+ * This function sets the timeout value for the SubBruteWorker instance. The timeout defines the maximum time allowed for the worker to complete its task before it is interrupted.
+ *
+ * @param instance A pointer to the SubBruteWorker instance.
+ * @param timeout The timeout value in milliseconds.
+ */
 void subbrute_worker_set_timeout(SubBruteWorker* instance, uint8_t timeout);
+
+/**
+ * @brief Retrieves the number of repeated substrings found by the SubBruteWorker instance.
+ *
+ * This function returns the count of repeated substrings found during the execution of the SubBruteWorker instance.
+ *
+ * @param instance A pointer to the SubBruteWorker instance.
+ * @return The number of repeated substrings.
+ */
 uint8_t subbrute_worker_get_repeats(SubBruteWorker* instance);
+
+/**
+ * @brief Set the number of repeats for the SubBruteWorker instance.
+ *
+ * This function sets the number of repeats for the SubBruteWorker instance. The repeats
+ * determines how many times a certain operation should be repeated.
+ *
+ * @param instance A pointer to the SubBruteWorker instance.
+ * @param repeats The number of repeats to be set.
+ */
 void subbrute_worker_set_repeats(SubBruteWorker* instance, uint8_t repeats);
+
+/**
+ * @brief Get the value of te from a SubBruteWorker instance.
+ *
+ * This function returns the value of the te member variable of the SubBruteWorker instance.
+ *
+ * @param instance A pointer to the SubBruteWorker instance.
+ * @return The value of the te member variable.
+ */
 uint32_t subbrute_worker_get_te(SubBruteWorker* instance);
+
+/**
+ * @brief Set the value of te for the SubBruteWorker instance.
+ *
+ * This function sets the value of the te member variable for the given SubBruteWorker instance.
+ * The te value determines the threshold for the worker to stop processing.
+ *
+ * @param instance Pointer to the SubBruteWorker instance
+ * @param te The threshold value to set
+ */
 void subbrute_worker_set_te(SubBruteWorker* instance, uint32_t te);
 
 // void subbrute_worker_timeout_inc(SubBruteWorker* instance);
 
 // void subbrute_worker_timeout_dec(SubBruteWorker* instance);
 
+/**
+  * @brief Checks if transmission is allowed for the given value.
+  *
+  * This function checks the transmission allowance for the given value based on the state of the SubBruteWorker instance.
+  *
+  * @param instance A pointer to the SubBruteWorker instance.
+  * @param value The value to check transmission allowance for.
+  *
+  * @return True if transmission is allowed for the given value, false otherwise.
+  */
 bool subbrute_worker_is_tx_allowed(SubBruteWorker* instance, uint32_t value);

+ 38 - 0
subghz_bruteforcer/helpers/subbrute_worker_private.h

@@ -6,6 +6,13 @@
 #include <lib/subghz/receiver.h>
 #include <lib/subghz/environment.h>
 
+/**
+ * @class SubBruteWorker
+ * @brief Class representing a SubBruteWorker object.
+ *
+ * The SubBruteWorker class is responsible for performing sub-brute forcing tasks.
+ * It manages the state, configuration and execution of the sub-brute forcing algorithm.
+ */
 struct SubBruteWorker {
     SubBruteWorkerState state;
     volatile bool worker_running;
@@ -45,6 +52,37 @@ struct SubBruteWorker {
     void* context;
 };
 
+/**
+ * @brief This function is the entry point for the sub-brute worker thread.
+ *
+ * @param context A pointer to the context data for the worker thread.
+ * @return int32_t The return status of the worker thread.
+ *
+ * The sub-brute worker thread performs a sub-brute force operation based on the given context.
+ * It takes the context as an input, processes the data, and returns a status code.
+ * The function is used as an entry point for the worker thread.
+ */
 int32_t subbrute_worker_thread(void* context);
+
+/**
+ * @brief Transmits FlipperFormat using subGHz.
+ *
+ * This function transmits the specified FlipperFormat using the subGHz
+ * protocol.
+ *
+ * @param instance The SubBruteWorker instance.
+ * @param flipper_format Pointer to the FlipperFormat to be transmitted.
+ */
 void subbrute_worker_subghz_transmit(SubBruteWorker* instance, FlipperFormat* flipper_format);
+
+/**
+ * @brief Send a callback for a SubBruteWorker instance.
+ *
+ * This function is used to send a callback for the SubBruteWorker instance. The callback is triggered
+ * when certain conditions are met during the worker's execution.
+ *
+ * @param instance The SubBruteWorker instance for which the callback is sent.
+ *
+ * @note This function does not return any values.
+ */
 void subbrute_worker_send_callback(SubBruteWorker* instance);

+ 11 - 5
subghz_bruteforcer/scenes/subbrute_scene_save_name.c

@@ -9,11 +9,17 @@ void subbrute_scene_save_name_on_enter(void* context) {
 
     // Setup view
     TextInput* text_input = instance->text_input;
-    name_generator_make_auto(
-        instance->text_store,
-        sizeof(instance->text_store),
-        subbrute_protocol_file(instance->device->protocol_info->file));
-
+    if(instance->device->attack == SubBruteAttackLoadFile) {
+        name_generator_make_auto(
+            instance->text_store,
+            sizeof(instance->text_store),
+            subbrute_protocol_file(instance->device->file_protocol_info->file));
+    } else {
+        name_generator_make_auto(
+            instance->text_store,
+            sizeof(instance->text_store),
+            subbrute_protocol_file(instance->device->protocol_info->file));
+    }
     text_input_set_header_text(text_input, "Name of file");
     text_input_set_result_callback(
         text_input,

+ 70 - 0
subghz_bruteforcer/subbrute_custom_event.h

@@ -1,5 +1,75 @@
 #pragma once
 
+/**
+ * @enum SubBruteCustomEvent
+ * @brief Enumerates the custom event types used in the SubBrute application.
+ *
+ * This enumeration defines custom event types used in the SubBrute application.
+ * The first 100 event types are reserved for button types and indexes, starting
+ * from 0. The remaining event types are specific to the application and are used
+ * to handle various events.
+ *
+ * @note These event types are used to define custom events in the application's
+ *       event handling system. They should be used to specify the type of custom
+ *       events and differentiate them from other events.
+ *
+ * @var SubBruteCustomEventTypeReserved
+ * Reserved event type for button types and indexes. Starting from 0.
+ *
+ * @var SubBruteCustomEventTypeBackPressed
+ * Event type for the back button press event.
+ *
+ * @var SubBruteCustomEventTypeIndexSelected
+ * Event type for the index selection event.
+ *
+ * @var SubBruteCustomEventTypeTransmitStarted
+ * Event type for the transmit start event.
+ *
+ * @var SubBruteCustomEventTypeError
+ * Event type for the error event.
+ *
+ * @var SubBruteCustomEventTypeTransmitFinished
+ * Event type for the transmit finish event.
+ *
+ * @var SubBruteCustomEventTypeTransmitNotStarted
+ * Event type for the transmit not started event.
+ *
+ * @var SubBruteCustomEventTypeTransmitCustom
+ * Event type for the custom transmit event.
+ *
+ * @var SubBruteCustomEventTypeSaveFile
+ * Event type for the save file event.
+ *
+ * @var SubBruteCustomEventTypeExtraSettings
+ * Event type for the extra settings event.
+ *
+ * @var SubBruteCustomEventTypeUpdateView
+ * Event type for the update view event.
+ *
+ * @var SubBruteCustomEventTypeChangeStepUp
+ * Event type for the change step up event.
+ *
+ * @var SubBruteCustomEventTypeChangeStepDown
+ * Event type for the change step down event.
+ *
+ * @var SubBruteCustomEventTypeChangeStepUpMore
+ * Event type for the change step up more event.
+ *
+ * @var SubBruteCustomEventTypeChangeStepDownMore
+ * Event type for the change step down more event.
+ *
+ * @var SubBruteCustomEventTypeMenuSelected
+ * Event type for the menu selection event.
+ *
+ * @var SubBruteCustomEventTypeTextEditDone
+ * Event type for the text edit done event.
+ *
+ * @var SubBruteCustomEventTypePopupClosed
+ * Event type for the popup close event.
+ *
+ * @var SubBruteCustomEventTypeLoadFile
+ * Event type for the load file event.
+ */
 typedef enum {
     // Reserve first 100 events for button types and indexes, starting from 0
     SubBruteCustomEventTypeReserved = 100,

+ 97 - 0
subghz_bruteforcer/subbrute_device.h

@@ -11,6 +11,14 @@
 #define SUBBRUTE_PATH EXT_PATH("subghz")
 #define SUBBRUTE_FILE_EXT ".sub"
 
+/**
+ * @enum SubBruteFileResult
+ * @brief Represents the possible results of a sub-brute force file operation.
+ *
+ * This enumeration defines a set of possible results that can occur when performing
+ * a sub-brute force operation on a file. Each result represents a specific error or
+ * condition that can occur during the operation.
+ */
 typedef enum {
     SubBruteFileResultUnknown,
     SubBruteFileResultOk,
@@ -28,6 +36,13 @@ typedef enum {
     SubBruteFileResultMissingOrIncorrectTe,
 } SubBruteFileResult;
 
+/**
+ * @struct SubBruteDevice
+ * @brief Represents a device for SubBrute attack.
+ *
+ * This structure contains information and state variables required for performing
+ * a SubBrute attack.
+ */
 typedef struct {
     const SubBruteProtocol* protocol_info;
     SubBruteProtocol* file_protocol_info;
@@ -55,20 +70,102 @@ typedef struct {
     uint8_t bit_index;
 } SubBruteDevice;
 
+/**
+ * @brief Allocates memory for a SubBruteDevice structure.
+ *
+ * This function allocates memory for a SubBruteDevice structure and
+ * initializes it using the given SubGhzDevice.
+ *
+ * @param radio_device The SubGhzDevice used to initialize the SubBruteDevice.
+ * @return A pointer to the allocated SubBruteDevice structure.
+ */
 SubBruteDevice* subbrute_device_alloc(const SubGhzDevice* radio_device);
+
+/**
+ * @brief Frees the memory allocated for a SubBruteDevice instance.
+ *
+ * This function frees the memory allocated for a SubBruteDevice instance.
+ * After calling this function, the instance is no longer valid and should not be used.
+ *
+ * @param instance Pointer to the SubBruteDevice instance to be freed.
+ */
 void subbrute_device_free(SubBruteDevice* instance);
 
+/**
+ * Saves a file with the specified key name using the given SubBruteDevice instance.
+ *
+ * @param instance The SubBruteDevice instance to use for saving the file.
+ * @param key_name The name of the key to be used for saving the file.
+ * @return True if the file is successfully saved, False otherwise.
+ */
 bool subbrute_device_save_file(SubBruteDevice* instance, const char* key_name);
+
+/**
+ * @brief Retrieves the description for a specific device error.
+ *
+ * This function returns a string that describes the given device error ID. The error ID
+ * should be obtained from a SubBruteFileResult value. The returned string provides
+ * additional information about the error, such as its cause or possible solutions.
+ *
+ * @param error_id The device error ID for which to retrieve the description.
+ *
+ * @return A pointer to a constant string containing the description of the device error.
+ */
 const char* subbrute_device_error_get_desc(SubBruteFileResult error_id);
 SubBruteFileResult subbrute_device_attack_set(
     SubBruteDevice* context,
     SubBruteAttacks type,
     uint8_t extra_repeats);
+
+/**
+ * @brief Loads data from a file into a SubBruteDevice context.
+ *
+ * This function reads data from the specified file and populates the
+ * SubBruteDevice context with the loaded data. The file contents are
+ * expected to be in a specific format supported by the SubBruteDevice.
+ * Use this function to initialize the context with pre-existing data.
+ *
+ * @param context Pointer to the SubBruteDevice context to be populated.
+ * @param file_path Path of the file to load data from.
+ * @return The status of the loading operation.
+ *     - Returns 0 if the loading is successful.
+ *     - Returns a non-zero value if an error occurs during loading.
+ */
 uint8_t subbrute_device_load_from_file(SubBruteDevice* context, const char* file_path);
 
+/**
+ * @brief Adds a step to the SubBruteDevice instance.
+ *
+ * This function adds a step to the given SubBruteDevice instance. It updates
+ * the internal state of the device accordingly.
+ *
+ * @param[in,out] instance The SubBruteDevice instance.
+ * @param[in] step The step to be added.
+ *
+ * @return The updated value of the device state after adding the step.
+ */
 uint64_t subbrute_device_add_step(SubBruteDevice* instance, int8_t step);
 
+/**
+ * @brief Frees the memory allocated for the protocol information of a SubBruteDevice instance.
+ *
+ * This function will deallocate the memory used by the protocol information of a SubBruteDevice instance,
+ * including all the individual protocol objects and their data.
+ *
+ * @param instance Pointer to the SubBruteDevice instance.
+ */
 void subbrute_device_free_protocol_info(SubBruteDevice* instance);
+
+/**
+ * @brief Set the default values for a SubBruteDevice attack configuration.
+ *
+ * This function sets the default values for a SubBruteDevice attack configuration based on the specified default_attack type.
+ *
+ * @param context Pointer to a SubBruteDevice instance.
+ * @param default_attack The default attack type to use.
+ *
+ * @see SubBruteDevice
+ */
 void subbrute_device_attack_set_default_values(
     SubBruteDevice* context,
     SubBruteAttacks default_attack);

+ 46 - 1
subghz_bruteforcer/subbrute_i.h

@@ -33,12 +33,19 @@
 #include "views/subbrute_attack_view.h"
 #include "views/subbrute_main_view.h"
 
-#define SUBBRUTEFORCER_VER "Sub-GHz BruteForcer 3.9"
+#define SUBBRUTEFORCER_VER "Sub-GHz BruteForcer 3.A"
 
 #ifdef FURI_DEBUG
 //#define SUBBRUTE_FAST_TRACK false
 #endif
 
+/**
+ * @enum SubBruteView
+ * @brief An enumeration representing the different views of the SubBrute application
+ *
+ * This enumeration represents the possible views that the SubBrute application can have. Each view
+ * corresponds to a specific screen or UI element in the application.
+ */
 typedef enum {
     SubBruteViewNone,
     SubBruteViewMain,
@@ -51,6 +58,12 @@ typedef enum {
     SubBruteViewVarList,
 } SubBruteView;
 
+/**
+ * @class SubBruteState
+ * @brief Represents the state of a SubBrute application.
+ *
+ * This class contains the various elements and variables necessary for the functioning of a SubBrute application.
+ */
 struct SubBruteState {
     // GUI elements
     NotificationApp* notifications;
@@ -84,6 +97,38 @@ struct SubBruteState {
     SubBruteSettings* settings;
 };
 
+/**
+ * @brief Function to show or hide a loading popup.
+ *
+ * This function is used to display or hide a loading popup in a user interface.
+ * The loading popup appears when an action is being performed that may take some time to complete.
+ *
+ * @param context A pointer to the context object associated with the loading popup.
+ * @param show A boolean value indicating whether to display or hide the loading popup.
+ */
 void subbrute_show_loading_popup(void* context, bool show);
+
+/**
+ * @brief Callback function for text input in the sub-brute module.
+ *
+ * This function serves as a callback for handling text input in the sub-brute module.
+ * It should be registered as a callback function for text input events.
+ *
+ * @param context A pointer to additional context data (if any).
+ *
+ * @return None
+ */
 void subbrute_text_input_callback(void* context);
+
+/**
+ * @brief Callback function called when a popup window is closed.
+ *
+ * This function is called when a popup window is closed. It can be used to perform
+ * any necessary cleanup or additional processing after the popup window is closed.
+ *
+ * @param context A void pointer to the context data associated with the popup window.
+ *                It can be used to pass any additional information needed by the callback function.
+ *
+ * @return void
+ */
 void subbrute_popup_closed_callback(void* context);

+ 233 - 2
subghz_bruteforcer/subbrute_protocols.h

@@ -7,6 +7,36 @@
 
 #define SUBBRUTE_PROTOCOL_MAX_REPEATS 9
 
+/**
+ * @enum SubBruteFileProtocol
+ * @brief Enum defining various file protocols used in a system
+ *
+ * This enum defines different file protocols that can be used in the system.
+ * Each file protocol is identified by its name.
+ *
+ * The possible values for this enum are:
+ * - CAMEFileProtocol: CAME file protocol
+ * - NICEFileProtocol: NICE file protocol
+ * - ChamberlainFileProtocol: Chamberlain file protocol
+ * - LinearFileProtocol: Linear file protocol
+ * - LinearDeltaFileProtocol: Linear Delta file protocol
+ * - PrincetonFileProtocol: Princeton file protocol
+ * - RAWFileProtocol: RAW file protocol
+ * - BETTFileProtocol: BETT file protocol
+ * - ClemsaFileProtocol: Clemsa file protocol
+ * - DoitrandFileProtocol: Doitrand file protocol
+ * - GateTXFileProtocol: GateTX file protocol
+ * - MagellanFileProtocol: Magellan file protocol
+ * - IntertechnoV3FileProtocol: Intertechno V3 file protocol
+ * - AnsonicFileProtocol: Ansonic file protocol
+ * - SMC5326FileProtocol: SMC5326 file protocol
+ * - UNILARMFileProtocol: UNILARM file protocol
+ * - PT2260FileProtocol: PT2260 file protocol
+ * - HoneywellFileProtocol: Honeywell file protocol
+ * - HoltekFileProtocol: Holtek file protocol
+ * - UnknownFileProtocol: Unknown file protocol
+ * - TotalFileProtocol: Total file protocol
+ */
 typedef enum {
     CAMEFileProtocol,
     NICEFileProtocol,
@@ -31,6 +61,56 @@ typedef enum {
     TotalFileProtocol,
 } SubBruteFileProtocol;
 
+/**
+ * @enum SubBruteAttacks
+ *
+ * Enumeration of all supported sub-brute attacks.
+ *
+ * The `SubBruteAttacks` represents the different types of sub-brute attacks
+ * that can be performed. Each attack has a unique identifier, which can be used
+ * to specify the attack when calling functions that handle sub-brute attacks.
+ *
+ * The possible values of `SubBruteAttacks` are as follows:
+ *
+ * - `SubBruteAttackCAME12bit303`: CAME 12-bit 303 MHz sub-brute attack.
+ * - `SubBruteAttackCAME12bit307`: CAME 12-bit 307 MHz sub-brute attack.
+ * - `SubBruteAttackCAME12bit315`: CAME 12-bit 315 MHz sub-brute attack.
+ * - `SubBruteAttackCAME12bit433`: CAME 12-bit 433 MHz sub-brute attack.
+ * - `SubBruteAttackCAME12bit868`: CAME 12-bit 868 MHz sub-brute attack.
+ * - `SubBruteAttackNICE12bit433`: NICE 12-bit 433 MHz sub-brute attack.
+ * - `SubBruteAttackNICE12bit868`: NICE 12-bit 868 MHz sub-brute attack.
+ * - `SubBruteAttackAnsonic12bit433075`: Ansonic 12-bit 433.075 MHz sub-brute attack.
+ * - `SubBruteAttackAnsonic12bit433`: Ansonic 12-bit 433 MHz sub-brute attack.
+ * - `SubBruteAttackAnsonic12bit434`: Ansonic 12-bit 434 MHz sub-brute attack.
+ * - `SubBruteAttackHoltek12bitFM433`: Holtek 12-bit FM 433 MHz sub-brute attack.
+ * - `SubBruteAttackHoltek12bitAM433`: Holtek 12-bit AM 433 MHz sub-brute attack.
+ * - `SubBruteAttackHoltek12bitAM315`: Holtek 12-bit AM 315 MHz sub-brute attack.
+ * - `SubBruteAttackHoltek12bitAM868`: Holtek 12-bit AM 868 MHz sub-brute attack.
+ * - `SubBruteAttackHoltek12bitAM915`: Holtek 12-bit AM 915 MHz sub-brute attack.
+ * - `SubBruteAttackChamberlain9bit300`: Chamberlain 9-bit 300 MHz sub-brute attack.
+ * - `SubBruteAttackChamberlain9bit315`: Chamberlain 9-bit 315 MHz sub-brute attack.
+ * - `SubBruteAttackChamberlain9bit390`: Chamberlain 9-bit 390 MHz sub-brute attack.
+ * - `SubBruteAttackChamberlain9bit433`: Chamberlain 9-bit 433 MHz sub-brute attack.
+ * - `SubBruteAttackChamberlain8bit300`: Chamberlain 8-bit 300 MHz sub-brute attack.
+ * - `SubBruteAttackChamberlain8bit315`: Chamberlain 8-bit 315 MHz sub-brute attack.
+ * - `SubBruteAttackChamberlain8bit390`: Chamberlain 8-bit 390 MHz sub-brute attack.
+ * - `SubBruteAttackChamberlain7bit300`: Chamberlain 7-bit 300 MHz sub-brute attack.
+ * - `SubBruteAttackChamberlain7bit315`: Chamberlain 7-bit 315 MHz sub-brute attack.
+ * - `SubBruteAttackChamberlain7bit390`: Chamberlain 7-bit 390 MHz sub-brute attack.
+ * - `SubBruteAttackLinear10bit300`: Linear 10-bit 300 MHz sub-brute attack.
+ * - `SubBruteAttackLinear10bit310`: Linear 10-bit 310 MHz sub-brute attack.
+ * - `SubBruteAttackLinearDelta8bit310`: Linear Delta 8-bit 310 MHz sub-brute attack.
+ * - `SubBruteAttackUNILARM24bit330`: UNILARM 24-bit 330 MHz sub-brute attack.
+ * - `SubBruteAttackUNILARM24bit433`: UNILARM 24-bit 433 MHz sub-brute attack.
+ * - `SubBruteAttackSMC532624bit330`: SMC5326 24-bit 330 MHz sub-brute attack.
+ * - `SubBruteAttackSMC532624bit433`: SMC5326 6-bit 433 MHz sub-brute attack.
+ * - `SubBruteAttackPT226024bit315`: PT2260 24-bit 315 MHz sub-brute attack.
+ * - `SubBruteAttackPT226024bit330`: PT2260 24-bit 330 MHz sub-brute attack.
+ * - `SubBruteAttackPT226024bit390`: PT2260 24-bit 390 MHz sub-brute attack.
+ * - `SubBruteAttackPT226024bit433`: PT2260 24-bit 433 MHz sub-brute attack.
+ * - `SubBruteAttackLoadFile`: Sub-brute attack using values loaded from a file.
+ * - `SubBruteAttackTotalCount`: Total number of sub-brute attacks.
+ */
 typedef enum {
     SubBruteAttackCAME12bit303,
     SubBruteAttackCAME12bit307,
@@ -72,6 +152,13 @@ typedef enum {
     SubBruteAttackTotalCount,
 } SubBruteAttacks;
 
+/**
+ * @struct SubBruteProtocol
+ * @brief Structure representing the SubBrute protocol.
+ *
+ * The SubBruteProtocol struct contains information about the protocol parameters such as frequency,
+ * bits, transmission time (te), repeat count, preset type, and file details using SubBruteFileProtocol.
+ */
 typedef struct {
     uint32_t frequency;
     uint8_t bits;
@@ -81,14 +168,95 @@ typedef struct {
     SubBruteFileProtocol file;
 } SubBruteProtocol;
 
+/**
+ * @brief Get the SubBruteProtocol object based on the given index
+ *
+ * This function returns the SubBruteProtocol object based on the provided index.
+ *
+ * @param index The index of the SubBruteProtocol
+ * @return const SubBruteProtocol* The pointer to the SubBruteProtocol object
+ */
 const SubBruteProtocol* subbrute_protocol(SubBruteAttacks index);
+
+/**
+ * @brief Retrieves a sub-GHz protocol preset for brute force attack.
+ *
+ * Given a FuriHalSubGhzPreset value, this function retrieves a sub-GHz protocol
+ * preset suitable for performing a brute force attack. The protocol preset is
+ * returned as a null-terminated string.
+ *
+ * @param preset The FuriHalSubGhzPreset value representing the desired sub-GHz
+ *               protocol preset.
+ * @return A null-terminated string representing the protocol preset.
+ */
 const char* subbrute_protocol_preset(FuriHalSubGhzPreset preset);
+
+/**
+ * @brief Determines the file protocol used by SubBrute
+ *
+ * This function takes a SubBruteFileProtocol and returns the corresponding file protocol used by SubBrute.
+ *
+ * @param protocol The SubBruteFileProtocol to retrieve the file protocol for
+ *
+ * @returns The file protocol as a C string
+ */
 const char* subbrute_protocol_file(SubBruteFileProtocol protocol);
+
+/**
+ * @brief Convert a preset name to a FuriHalSubGhzPreset.
+ *
+ * This function takes a preset name as a FuriString pointer and converts it to a corresponding FuriHalSubGhzPreset value.
+ * The converted preset is returned as a FuriHalSubGhzPreset value. If the preset name is not recognized, the behavior is undefined.
+ *
+ * @param preset_name The preset name to be converted.
+ *
+ * @return The converted FuriHalSubGhzPreset value.
+ */
 FuriHalSubGhzPreset subbrute_protocol_convert_preset(FuriString* preset_name);
+
+/**
+ * @brief Creates a SubBruteFileProtocol with the given name.
+ *
+ * @param name The name of the protocol.
+ * @return The created SubBruteFileProtocol.
+ */
 SubBruteFileProtocol subbrute_protocol_file_protocol_name(FuriString* name);
+
+/**
+ * @brief Get the number of protocol repeats for a specific SubBrute attack.
+ *
+ * This function returns the number of protocol repeats for a specific SubBrute attack, identified by its index.
+ *
+ * @param index The index of the SubBrute attack.
+ * @return The number of protocol repeats for the specified SubBrute attack.
+ */
 uint8_t subbrute_protocol_repeats_count(SubBruteAttacks index);
+
+/**
+ * @brief Retrieves the protocol name for a given SubBrute attack.
+ *
+ * This function returns the protocol name associated with the specified SubBrute attack.
+ *
+ * @param index The index of the SubBrute attack.
+ * @return The protocol name as a constant character pointer.
+ */
 const char* subbrute_protocol_name(SubBruteAttacks index);
 
+/**
+ * @brief Executes a sub-brute force attack with default payload.
+ *
+ * This function performs a sub-brute force attack using the default payload on the specified stream and file protocol.
+ * It continues the attack in steps, with each step increasing the payload by a specified number of bits.
+ *
+ * @param stream The stream to perform the attack on.
+ * @param file The file protocol to use for the attack.
+ * @param step The number of bits to increase the payload with in each step.
+ * @param bits The initial number of bits in the payload.
+ * @param te The timeout value in milliseconds.
+ * @param repeat The number of times to repeat the attack.
+ *
+ * @note The function does not return any value.
+ */
 void subbrute_protocol_default_payload(
     Stream* stream,
     SubBruteFileProtocol file,
@@ -96,6 +264,25 @@ void subbrute_protocol_default_payload(
     uint8_t bits,
     uint32_t te,
     uint8_t repeat);
+
+/**
+ * @brief Performs a sub-brute force protocol operation with file payload.
+ *
+ * This function takes in a stream, step, bits, te, repeat, bit_index,
+ * file_key, and two_bytes as input parameters and performs a sub-brute
+ * force protocol operation with a file payload.
+ *
+ * @param stream The Stream object to operate on.
+ * @param step The step value to use during the operation.
+ * @param bits The number of bits to use.
+ * @param te The te value to use during the operation.
+ * @param repeat The number of times to repeat the operation.
+ * @param bit_index The bit index to use during the operation.
+ * @param file_key The file key to use during the operation.
+ * @param two_bytes A boolean indicating whether to use two bytes in the operation.
+ *
+ * @return None
+ */
 void subbrute_protocol_file_payload(
     Stream* stream,
     uint64_t step,
@@ -105,6 +292,20 @@ void subbrute_protocol_file_payload(
     uint8_t bit_index,
     uint64_t file_key,
     bool two_bytes);
+
+/**
+ * @brief Generates a file using the SubBrute protocol with default settings.
+ *
+ * This function generates a file using the SubBrute protocol with default settings.
+ *
+ * @param stream The stream used for writing the file.
+ * @param frequency The frequency of the SubBrute protocol.
+ * @param preset The SubGhzPreset used for transmission.
+ * @param file The SubBruteFileProtocol used for generating the file.
+ * @param step The step size used for generating the file.
+ * @param bits The number of bits to generate for each interval.
+ * @param te The duration of each transmission interval in milliseconds.
+ */
 void subbrute_protocol_default_generate_file(
     Stream* stream,
     uint32_t frequency,
@@ -113,6 +314,24 @@ void subbrute_protocol_default_generate_file(
     uint64_t step,
     uint8_t bits,
     uint32_t te);
+
+/**
+ * @brief Generates a file for the SubBrute protocol with the given parameters.
+ *
+ * This function generates a file for the SubBrute protocol using the provided parameters.
+ * The generated file can be used for various purposes, such as testing or data analysis.
+ *
+ * @param stream The Stream to output the generated file to.
+ * @param frequency The frequency to use for the SubBrute protocol.
+ * @param preset The SubGhzPreset to use for the SubBrute protocol.
+ * @param file The SubBruteFileProtocol to generate.
+ * @param step The step value to use for the SubBrute protocol.
+ * @param bits The number of bits to use for each transmission in the SubBrute protocol.
+ * @param te The TE value to use for the SubBrute protocol.
+ * @param bit_index The starting bit index for the SubBrute protocol.
+ * @param file_key The file key to use for generating the SubBrute file.
+ * @param two_bytes Indicates whether two bytes should be used for each transmission (true) or not (false).
+ */
 void subbrute_protocol_file_generate_file(
     Stream* stream,
     uint32_t frequency,
@@ -124,5 +343,17 @@ void subbrute_protocol_file_generate_file(
     uint8_t bit_index,
     uint64_t file_key,
     bool two_bytes);
-uint64_t
-    subbrute_protocol_calc_max_value(SubBruteAttacks attack_type, uint8_t bits, bool two_bytes);
+
+/**
+ * @brief Calculates the maximum value based on the attack type, number of bits, and whether two bytes are used.
+ *
+ * This function calculates the maximum value that can be generated based on the specified attack type,
+ * number of bits, and whether two bytes are used. The result is returned as a 64-bit unsigned integer.
+ *
+ * @param attack_type   The type of attack to be performed (SubBruteAttacks).
+ * @param bits          The number of bits used for the attack (uint8_t).
+ * @param two_bytes     Whether two bytes are used for the attack (bool).
+ *
+ * @return The maximum value that can be generated based on the attack parameters (uint64_t).
+ */
+uint64_t subbrute_protocol_calc_max_value(SubBruteAttacks attack_type, uint8_t bits, bool two_bytes);

+ 84 - 0
subghz_bruteforcer/subbrute_settings.h

@@ -6,16 +6,100 @@
 #include <storage/storage.h>
 #include "subbrute_protocols.h"
 
+/**
+ * @struct SubBruteSettings
+ * @brief Structure to store settings for a sub-brute attack.
+ *
+ * This structure stores the settings for a sub-brute attack, such as an array of repeat values and
+ * the last index used.
+ */
 typedef struct {
     uint8_t repeat_values[SubBruteAttackTotalCount];
     uint32_t last_index;
 } SubBruteSettings;
 
+/**
+ * @brief Allocates memory for a SubBruteSettings structure.
+ *
+ * @return A pointer to a newly allocated SubBruteSettings structure.
+ * @note The returned structure should be freed using subbrute_settings_free() function.
+ */
 SubBruteSettings* subbrute_settings_alloc(void);
+
+/**
+ * @brief Frees the memory allocated for the SubBruteSettings instance and all its members.
+ *
+ * This function should be used to release the memory allocated for an instance of the SubBruteSettings structure.
+ * It ensures that all members of the structure are properly freed.
+ *
+ * @param instance The SubBruteSettings instance to be freed.
+ */
 void subbrute_settings_free(SubBruteSettings* instance);
+
+/**
+ * @brief Loads the settings for the SubBrute instance.
+ *
+ * This function loads the settings for the SubBrute instance and populates the SubBruteSettings structure
+ * pointed to by the given instance.
+ *
+ * @param instance A pointer to the SubBruteSettings structure to populate with the loaded settings.
+ */
 void subbrute_settings_load(SubBruteSettings* instance);
+
+/**
+ * @brief Saves the settings of the SubBrute instance.
+ *
+ * This function is used to save the settings of the SubBrute instance to a storage.
+ *
+ * @param instance A pointer to the SubBruteSettings instance.
+ *
+ * @note The settings will be saved to a storage. The exact storage and format
+ *       will depend on the implementation. It is the responsibility of the caller
+ *       to ensure that the instance is valid and has been initialized properly.
+ *       The caller should handle any errors that may occur during the saving process.
+ */
 bool subbrute_settings_save(SubBruteSettings* instance);
+
+/**
+ * @brief Sets the value for a specific attack in the SubBruteSettings instance.
+ *
+ * This function allows you to set the value for a specific attack in the SubBruteSettings instance.
+ *
+ * @param instance A pointer to the SubBruteSettings instance.
+ * @param index The index of the attack for which the value needs to be set.
+ * @param value The value to be set for the specified attack.
+ */
 void subbrute_settings_set_value(SubBruteSettings* instance, SubBruteAttacks index, uint8_t value);
+
+/**
+ * @brief Get the value of a specific attack setting in the SubBruteSettings instance.
+ *
+ * @param instance The pointer to the SubBruteSettings instance.
+ * @param index    The index of the attack setting to get the value of.
+ *
+ * @return The value of the specified attack setting.
+ *
+ * @note The index parameter should be one of the SubBruteAttacks enum values.
+ */
 uint8_t subbrute_settings_get_value(SubBruteSettings* instance, SubBruteAttacks index);
+
+/**
+ * @brief Sets the repeated values for the SubBruteSettings instance.
+ *
+ * This function sets the repeated values for the SubBruteSettings instance.
+ * The repeated values are used for the sub-brute operation.
+ *
+ * @param instance Pointer to the SubBruteSettings instance.
+ * @param repeated_values Pointer to an array of repeated values.
+ */
 void subbrute_settings_set_repeats(SubBruteSettings* instance, const uint8_t* repeated_values);
+
+/**
+ * @brief Gets the current number of repeats from the SubBruteSettings instance.
+ *
+ * This function retrieves the current number of repeats stored in the given SubBruteSettings instance.
+ *
+ * @param instance Pointer to the SubBruteSettings instance.
+ * @return The current number of repeats as a uint8_t.
+ */
 uint8_t subbrute_settings_get_current_repeats(SubBruteSettings* instance);

+ 65 - 0
subghz_bruteforcer/views/subbrute_attack_view.h

@@ -8,14 +8,79 @@
 typedef void (*SubBruteAttackViewCallback)(SubBruteCustomEvent event, void* context);
 typedef struct SubBruteAttackView SubBruteAttackView;
 
+/**
+ * @brief Sets the callback function and context for the SubBruteAttackView.
+ *
+ * This function sets the callback function and context that will be used by the SubBruteAttackView
+ * instance. The callback function will be called when a certain event occurs in the SubBruteAttackView.
+ * The context parameter will be passed to the callback function as an argument.
+ *
+ * @param instance The SubBruteAttackView instance to set the callback for.
+ * @param callback The callback function to be called when the event occurs.
+ * @param context The context to be passed to the callback function when it is called.
+ *
+ * @note The callback function should have the following signature:
+ *       void callback(void* context)
+ *
+ * @note The callback function should not take ownership of the instance, it should only perform
+ *       the necessary logic based on the event.
+ *
+ * @warning The instance parameter must not be NULL.
+ * @warning The callback parameter must not be NULL.
+ *
+ */
 void subbrute_attack_view_set_callback(
     SubBruteAttackView* instance,
     SubBruteAttackViewCallback callback,
     void* context);
+
+/**
+ * @brief Allocates memory for a new SubBruteAttackView object.
+ *
+ * This function allocates memory for a new SubBruteAttackView object on the heap and returns a pointer to it.
+ *
+ * @return A pointer to a newly allocated SubBruteAttackView object.
+ */
 SubBruteAttackView* subbrute_attack_view_alloc();
+
+/**
+ * @brief Frees the memory allocated for a SubBruteAttackView instance.
+ *
+ * @param instance Pointer to the SubBruteAttackView instance to free.
+ */
 void subbrute_attack_view_free(SubBruteAttackView* instance);
+
+/**
+ * @brief Retrieves the view associated with the SubBruteAttackView instance.
+ *
+ * @param instance The SubBruteAttackView instance to retrieve the view from.
+ *
+ * @return A pointer to the associated view.
+ */
 View* subbrute_attack_view_get_view(SubBruteAttackView* instance);
+
+/**
+ * @brief Sets the current step for the SubBruteAttackView instance.
+ *
+ * This function sets the current step of the SubBruteAttackView instance
+ * to the specified value.
+ *
+ * @param instance A pointer to the SubBruteAttackView instance.
+ * @param current_step The value to set as the current step.
+ *
+ * @note The current step represents the current progress of the attack view.
+ *       It should be an unsigned 64-bit integer.
+ */
 void subbrute_attack_view_set_current_step(SubBruteAttackView* instance, uint64_t current_step);
+
+/**
+ * @class SubBruteAttackView
+ * @brief Class for initializing the values of a SubBruteAttackView instance.
+ *
+ * The SubBruteAttackView class is used to store and initialize the values
+ * of a SubBruteAttackView instance. These values include the index, maximum value,
+ * current step, attack status, and extra repeats.
+ */
 void subbrute_attack_view_init_values(
     SubBruteAttackView* instance,
     uint8_t index,

+ 1 - 6
subghz_bruteforcer/views/subbrute_main_view.c

@@ -112,18 +112,12 @@ void subbrute_main_view_draw_is_byte_selected(Canvas* canvas, SubBruteMainViewMo
 #ifdef FURI_DEBUG
     //FURI_LOG_D(TAG, "key_from_file: %s", model->key_from_file);
 #endif
-    //char msg_index[18];
-    //snprintf(msg_index, sizeof(msg_index), "Field index: %d", model->index);
     canvas_set_font(canvas, FontSecondary);
     canvas_draw_str_aligned(
         canvas, 64, 17, AlignCenter, AlignTop, "Please select values to calc:");
 
     subbrute_main_view_center_displayed_key(
         canvas, model->key_from_file, model->index, model->two_bytes);
-    //const char* line = furi_string_get_cstr(menu_items);
-    //canvas_set_font(canvas, FontSecondary);
-    //canvas_draw_str_aligned(
-    //    canvas, 64, 37, AlignCenter, AlignTop, furi_string_get_cstr(menu_items));
 
     elements_button_center(canvas, "Select");
     if(model->index > 0) {
@@ -132,6 +126,7 @@ void subbrute_main_view_draw_is_byte_selected(Canvas* canvas, SubBruteMainViewMo
     if(model->index < 7) {
         elements_button_right(canvas, " ");
     }
+
     // Switch to another mode
     if(model->two_bytes) {
         elements_button_top_left(canvas, "One byte");

+ 118 - 0
subghz_bruteforcer/views/subbrute_main_view.h

@@ -9,14 +9,60 @@
 typedef void (*SubBruteMainViewCallback)(SubBruteCustomEvent event, void* context);
 typedef struct SubBruteMainView SubBruteMainView;
 
+/**
+ * @brief Sets the callback function and context for the SubBruteMainView instance.
+ *
+ * This function sets the callback function and context for the SubBruteMainView instance. The callback function will be
+ * invoked when specific events occur in the SubBruteMainView. The context parameter allows passing additional data
+ * to the callback function.
+ *
+ * @param instance Pointer to the SubBruteMainView instance.
+ * @param callback Pointer to the callback function.
+ * @param context Pointer to the context data.
+ */
 void subbrute_main_view_set_callback(
     SubBruteMainView* instance,
     SubBruteMainViewCallback callback,
     void* context);
 
+/**
+ * @brief Allocates memory for a new instance of SubBruteMainView.
+ *
+ * @return A pointer to the newly allocated SubBruteMainView object.
+ * @note The caller is responsible for freeing the allocated memory using the `subbrute_main_view_free` function.
+ */
 SubBruteMainView* subbrute_main_view_alloc();
+
+/**
+ * @brief Frees the memory allocated for a SubBruteMainView instance.
+ *
+ * This function frees all the memory allocated for the given SubBruteMainView instance,
+ * including its internal data structures.
+ *
+ * @param instance  The SubBruteMainView instance to be freed.
+ */
 void subbrute_main_view_free(SubBruteMainView* instance);
+
+/**
+ * @brief Get the view associated with the SubBruteMainView instance.
+ *
+ * This function returns the view associated with the given SubBruteMainView instance.
+ *
+ * @param instance The SubBruteMainView instance.
+ * @return A pointer to the View object.
+ */
 View* subbrute_main_view_get_view(SubBruteMainView* instance);
+
+/**
+ * @brief Sets the index and other parameters for the SubBruteMainView instance.
+ *
+ * @param instance The SubBruteMainView instance.
+ * @param idx The index value to be set.
+ * @param repeats Pointer to an array of repeat values.
+ * @param is_select_byte Select byte value true or false.
+ * @param two_bytes Two bytes value true or false.
+ * @param key_from_file The key value from file.
+ */
 void subbrute_main_view_set_index(
     SubBruteMainView* instance,
     uint8_t idx,
@@ -24,10 +70,82 @@ void subbrute_main_view_set_index(
     bool is_select_byte,
     bool two_bytes,
     uint64_t key_from_file);
+
+/**
+ * @brief Get the index of the current subview in the main view.
+ *
+ * This function retrieves the index of the current subview within the main view. The current
+ * subview is represented by a SubBruteMainView instance.
+ *
+ * @param instance A pointer to the SubBruteMainView instance.
+ * @return The index of the current subview.
+ */
 SubBruteAttacks subbrute_main_view_get_index(SubBruteMainView* instance);
+
+/**
+ * @brief Retrieves the repeats of the main view in the SubBrute application.
+ *
+ * This function returns the repeats of the main view in the SubBrute application as a constant pointer to an array of uint8_t values.
+ *
+ * @param instance A pointer to the SubBruteMainView instance.
+ * @return A constant pointer to an array of uint8_t values representing the repeats of the main view.
+ */
 const uint8_t* subbrute_main_view_get_repeats(SubBruteMainView* instance);
+
+/**
+ * @brief Retrieves two bytes from the SubBruteMainView instance.
+ *
+ * This function retrieves two bytes from the SubBruteMainView instance.
+ * It returns a boolean value indicating the success of the operation.
+ *
+ * @param instance The SubBruteMainView instance from which to retrieve two bytes.
+ *
+ * @return true if the bytes were successfully retrieved, false otherwise.
+ */
 bool subbrute_main_view_get_two_bytes(SubBruteMainView* instance);
+
+/**
+ * @brief The function handles the entry point for the brute force attack view.
+ *
+ * This function is responsible for handling the entry point for the brute force
+ * attack view. It takes a void pointer to the context data as an argument.
+ *
+ * @param context A void pointer to the context data.
+ */
 void subbrute_attack_view_enter(void* context);
+
+/**
+ * @brief Function to exit the subbrute attack view.
+ *
+ * This function is used to exit the subbrute attack view, by performing any necessary clean
+ * up operations and freeing up any allocated memory.
+ *
+ * @param context A pointer to the context of the subbrute attack view.
+ *                This context contains all the necessary data and variables required by the view.
+ *                It should not be NULL.
+ */
 void subbrute_attack_view_exit(void* context);
+
+/**
+ * @brief View input handler for subbrute attack.
+ *
+ * This function processes an input event and performs the appropriate action
+ * for the subbrute attack view. It is called by the main event loop.
+ *
+ * @param event       The input event to be processed.
+ * @param context     A pointer to the context data for the subbrute attack view.
+ * @return            Boolean indicating whether the input event was handled successfully.
+ *                    True if the event was handled successfully, false otherwise.
+ */
 bool subbrute_attack_view_input(InputEvent* event, void* context);
+
+/**
+ * @brief Draws a subbrute attack view on the given canvas.
+ *
+ * This function is responsible for drawing the subbrute attack view on the canvas.
+ * The provided canvas should already be initialized and in a valid state.
+ *
+ * @param canvas   The canvas on which the view should be drawn.
+ * @param context  A pointer to any additional context or data that may be needed for drawing.
+ */
 void subbrute_attack_view_draw(Canvas* canvas, void* context);