From 9f506aca21f621b5fabc57c9d02f2f03b4bbfd36 Mon Sep 17 00:00:00 2001 From: Clara K Date: Thu, 26 Jan 2023 00:18:15 +0100 Subject: [PATCH 01/26] Update ReadMe.md --- ReadMe.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ReadMe.md b/ReadMe.md index f8c94a7fc..4497d6889 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -19,6 +19,8 @@ The goal of this Firmware is to regularly bring out amazing updates based on wha

- The focus of this firmware is functionality & stability: If an App doesnt work, its gone +- Asset Packs: Are you tired of having to remake your custom animations after every update, switching manifests and having a hard time sharing them, especially once you modify scanning assets too? Those times are over. Scroll down to learn more + - Giving the level system a purpose: Right now, each level unlocks a new wallpaper. More on that below - Clean upgraded code: RM wrote some updates to certain files. These are... painful, to say the least. Here its all built with perfection in mind and integrated in a mostly clean way. I invite you all to compare the code with theirs. From 5134f44c09d39344a8747655c0d59864bb574b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Ha=C5=82adyn=20=28krzys=5Fh=29?= Date: Thu, 26 Jan 2023 09:28:36 +0100 Subject: [PATCH 02/26] nfc: Fix crash when using debug PCAP trace (#2338) --- lib/nfc/helpers/reader_analyzer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/nfc/helpers/reader_analyzer.c b/lib/nfc/helpers/reader_analyzer.c index af4869ca9..9bf37a60d 100644 --- a/lib/nfc/helpers/reader_analyzer.c +++ b/lib/nfc/helpers/reader_analyzer.c @@ -159,6 +159,7 @@ void reader_analyzer_stop(ReaderAnalyzer* instance) { } if(instance->pcap) { nfc_debug_pcap_free(instance->pcap); + instance->pcap = NULL; } } From 58fa504a5e8ec35b30d0c7f75363da0a45065604 Mon Sep 17 00:00:00 2001 From: Clara K Date: Thu, 26 Jan 2023 20:31:25 +0100 Subject: [PATCH 03/26] Update ReadMe.md --- ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index 4497d6889..60c5f54d6 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -181,4 +181,4 @@ This helps us a lot, thanks for the free license for this project! [PVS-Studio](https://pvs-studio.com/en/pvs-studio/?utm_source=github&utm_medium=organic&utm_campaign=open_source) - static analyzer for C, C++, C#, and Java code. ---- -

"What we do for ourselves dies with us. What we do for others and the world remains and is immortal.” ― Albert Pike

+

"What we do for ourselves dies with us. What we do for others and the world remains and is immortal.” ― Albert Pine

From 5a150fe4147459d151684cdda142aac71e6b85cb Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Fri, 27 Jan 2023 00:18:36 +0100 Subject: [PATCH 04/26] workflow stuff --- .github/workflows/build.yml | 130 ++++++++ .github/workflows/check_submodules.yml | 47 +++ .github/workflows/lint_c.yml | 47 +++ .github/workflows/lint_python.yml | 33 ++ .github/workflows/merge_report.yml | 45 +++ .github/workflows/pvs_studio.yml | 115 +++++++ .github/workflows/reindex.yml | 14 + .github/workflows/unit_tests.yml | 66 ++++ .github/workflows/updater_test.yml | 77 +++++ .../resources/nfc/assets/mf_classic_dict.nfc | 292 ++++++++++++++++-- 10 files changed, 846 insertions(+), 20 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/check_submodules.yml create mode 100644 .github/workflows/lint_c.yml create mode 100644 .github/workflows/lint_python.yml create mode 100644 .github/workflows/merge_report.yml create mode 100644 .github/workflows/pvs_studio.yml create mode 100644 .github/workflows/reindex.yml create mode 100644 .github/workflows/unit_tests.yml create mode 100644 .github/workflows/updater_test.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..6344bc846 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,130 @@ +name: 'Build' + +on: + push: + branches: + - dev + - "release*" + tags: + - '*' + pull_request: + +env: + TARGETS: f7 + DEFAULT_TARGET: f7 + FBT_TOOLCHAIN_PATH: /home/runner/work + +jobs: + main: + runs-on: ubuntu-latest + 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)" + fi + + - name: 'Checkout code' + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + + - name: 'Get commit details' + id: names + run: | + if [[ ${{ github.event_name }} == 'pull_request' ]]; then + TYPE="pull" + elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then + TYPE="tag" + else + TYPE="other" + fi + python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE" + echo random_hash=$(openssl rand -base64 40 | shasum -a 256 | awk '{print $1}') >> $GITHUB_OUTPUT + echo "event_type=$TYPE" >> $GITHUB_OUTPUT + + - name: 'Make artifacts directory' + run: | + rm -rf artifacts + mkdir artifacts + + - name: 'Bundle scripts' + if: ${{ !github.event.pull_request.head.repo.fork }} + run: | + tar czpf artifacts/flipper-z-any-scripts-${SUFFIX}.tgz scripts debug + + - name: 'Build the firmware' + run: | + set -e + for TARGET in ${TARGETS}; do + ./fbt TARGET_HW="$(echo "${TARGET}" | sed 's/f//')" \ + copro_dist 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 + mv dist/${TARGET}-*/* artifacts/ + done + + - name: "Check for uncommitted changes" + run: | + git diff --exit-code + + - name: 'Bundle resources' + if: ${{ !github.event.pull_request.head.repo.fork }} + run: | + 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: | + cp build/core2_firmware.tgz "artifacts/flipper-z-any-core2_firmware-${SUFFIX}.tgz" + + - name: 'Archive artifacts' + uses: actions/upload-artifact@v3 + with: + name: firmware + path: | + artifacts + + compact: + if: ${{ !startsWith(github.ref, 'refs/tags') }} + runs-on: ubuntu-latest + 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)" + fi + + - name: 'Checkout code' + uses: actions/checkout@v3 + with: + fetch-depth: 0 + submodules: true + ref: ${{ github.event.pull_request.head.sha }} + + - name: 'Get commit details' + run: | + if [[ ${{ github.event_name }} == 'pull_request' ]]; then + TYPE="pull" + elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then + TYPE="tag" + else + TYPE="other" + fi + 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 TARGET_HW="$(echo "${TARGET}" | sed 's/f//')" \ + updater_package DEBUG=0 COMPACT=1 + done diff --git a/.github/workflows/check_submodules.yml b/.github/workflows/check_submodules.yml new file mode 100644 index 000000000..2eb2027c9 --- /dev/null +++ b/.github/workflows/check_submodules.yml @@ -0,0 +1,47 @@ +name: 'Check submodules branch' + +on: + push: + branches: + - dev + - "release*" + tags: + - '*' + pull_request: + +jobs: + check_protobuf: + runs-on: [self-hosted, FlipperZeroShell] + 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)" + fi + + - name: 'Checkout code' + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + + - name: 'Check protobuf branch' + run: | + git submodule update --init + SUB_PATH="assets/protobuf"; + SUB_BRANCH="dev"; + SUB_COMMITS_MIN=40; + cd "$SUB_PATH"; + SUBMODULE_HASH="$(git rev-parse HEAD)"; + BRANCHES=$(git branch -r --contains "$SUBMODULE_HASH"); + COMMITS_IN_BRANCH="$(git rev-list --count dev)"; + if [ $COMMITS_IN_BRANCH -lt $SUB_COMMITS_MIN ]; then + echo "name=fails::error" >> $GITHUB_OUTPUT + echo "::error::Error: Too low commits in $SUB_BRANCH of submodule $SUB_PATH: $COMMITS_IN_BRANCH(expected $SUB_COMMITS_MIN+)"; + exit 1; + fi + if ! grep -q "/$SUB_BRANCH" <<< "$BRANCHES"; then + echo "name=fails::error" >> $GITHUB_OUTPUT + echo "::error::Error: Submodule $SUB_PATH is not on branch $SUB_BRANCH"; + exit 1; + fi diff --git a/.github/workflows/lint_c.yml b/.github/workflows/lint_c.yml new file mode 100644 index 000000000..a6fd5127c --- /dev/null +++ b/.github/workflows/lint_c.yml @@ -0,0 +1,47 @@ +name: 'Lint C/C++ with clang-format' + +on: + push: + branches: + - dev + - "release*" + tags: + - '*' + pull_request: + +env: + TARGETS: f7 + FBT_TOOLCHAIN_PATH: /runner/_work + SET_GH_OUTPUT: 1 + +jobs: + lint_c_cpp: + runs-on: [self-hosted,FlipperZeroShell] + 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)" + fi + + - name: 'Checkout code' + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + + - name: 'Check code formatting' + id: syntax_check + run: ./fbt lint + + - name: Report code formatting errors + if: failure() && steps.syntax_check.outputs.errors && github.event.pull_request + uses: peter-evans/create-or-update-comment@v1 + with: + issue-number: ${{ github.event.pull_request.number }} + body: | + Please fix following code formatting errors: + ``` + ${{ steps.syntax_check.outputs.errors }} + ``` + You might want to run `./fbt format` for an auto-fix. diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml new file mode 100644 index 000000000..66c36064c --- /dev/null +++ b/.github/workflows/lint_python.yml @@ -0,0 +1,33 @@ +name: 'Python Lint' + +on: + push: + branches: + - dev + - "release*" + tags: + - '*' + pull_request: + +env: + FBT_TOOLCHAIN_PATH: /runner/_work + SET_GH_OUTPUT: 1 + +jobs: + lint_python: + runs-on: [self-hosted,FlipperZeroShell] + 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)" + fi + + - name: 'Checkout code' + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + + - name: 'Check code formatting' + run: ./fbt lint_py diff --git a/.github/workflows/merge_report.yml b/.github/workflows/merge_report.yml new file mode 100644 index 000000000..13fab0948 --- /dev/null +++ b/.github/workflows/merge_report.yml @@ -0,0 +1,45 @@ +name: 'Check FL ticket in PR name' + +on: + push: + branches: + - dev + +env: + FBT_TOOLCHAIN_PATH: /runner/_work + +jobs: + merge_report: + runs-on: [self-hosted,FlipperZeroShell] + 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)" + fi + + - name: 'Checkout code' + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + + - name: 'Get commit details' + run: | + if [[ ${{ github.event_name }} == 'pull_request' ]]; then + TYPE="pull" + elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then + TYPE="tag" + else + TYPE="other" + fi + python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE" + + - name: 'Check ticket and report' + run: | + source scripts/toolchain/fbtenv.sh + python3 -m pip install slack_sdk + python3 scripts/merge_report_qa.py \ + ${{ secrets.QA_REPORT_SLACK_TOKEN }} \ + ${{ secrets.QA_REPORT_SLACK_CHANNEL }} + diff --git a/.github/workflows/pvs_studio.yml b/.github/workflows/pvs_studio.yml new file mode 100644 index 000000000..46ee8801d --- /dev/null +++ b/.github/workflows/pvs_studio.yml @@ -0,0 +1,115 @@ +name: 'Static C/C++ analysis with PVS-Studio' + +on: + push: + branches: + - dev + - "release*" + tags: + - '*' + pull_request: + +env: + TARGETS: f7 + DEFAULT_TARGET: f7 + FBT_TOOLCHAIN_PATH: /runner/_work + +jobs: + analyse_c_cpp: + if: ${{ !github.event.pull_request.head.repo.fork }} + runs-on: [self-hosted, FlipperZeroShell] + 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)" + fi + + - name: 'Checkout code' + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + + - name: 'Get commit details' + id: names + run: | + if [[ ${{ github.event_name }} == 'pull_request' ]]; then + TYPE="pull" + elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then + TYPE="tag" + else + TYPE="other" + fi + python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE" + + - name: 'Make reports directory' + run: | + rm -rf reports/ + mkdir reports + + - name: 'Generate compile_comands.json' + run: | + ./fbt COMPACT=1 version_json proto_ver icons firmware_cdb dolphin_internal dolphin_blocking _fap_icons api_syms + + - name: 'Static code analysis' + run: | + source scripts/toolchain/fbtenv.sh + pvs-studio-analyzer credentials ${{ secrets.PVS_STUDIO_CREDENTIALS }} + pvs-studio-analyzer analyze \ + @.pvsoptions \ + -C gccarm \ + -j$(grep -c processor /proc/cpuinfo) \ + -f build/f7-firmware-DC/compile_commands.json \ + -o PVS-Studio.log + + - name: 'Convert PVS-Studio output to html and detect warnings' + id: pvs-warn + run: | + WARNINGS=0 + plog-converter \ + -a GA:1,2,3 \ + -t fullhtml \ + --indicate-warnings \ + PVS-Studio.log \ + -o reports/${DEFAULT_TARGET}-${SUFFIX} || WARNINGS=1 + echo "warnings=${WARNINGS}" >> $GITHUB_OUTPUT + + - name: 'Upload artifacts to update server' + if: ${{ !github.event.pull_request.head.repo.fork && (steps.pvs-warn.outputs.warnings != 0) }} + run: | + mkdir -p ~/.ssh + ssh-keyscan -p ${{ secrets.RSYNC_DEPLOY_PORT }} -H ${{ secrets.RSYNC_DEPLOY_HOST }} > ~/.ssh/known_hosts + echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key; + 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/"${BRANCH_NAME}/"; + rm ./deploy_key; + + - name: 'Find Previous Comment' + if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request && (steps.pvs-warn.outputs.warnings != 0) }} + uses: peter-evans/find-comment@v2 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: 'PVS-Studio report for commit' + + - name: 'Create or update comment' + if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request && (steps.pvs-warn.outputs.warnings != 0) }} + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + **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 + + - name: 'Raise exception' + if: ${{ steps.pvs-warn.outputs.warnings != 0 }} + run: | + echo "Please fix all PVS varnings before merge" + exit 1 + diff --git a/.github/workflows/reindex.yml b/.github/workflows/reindex.yml new file mode 100644 index 000000000..ea850e705 --- /dev/null +++ b/.github/workflows/reindex.yml @@ -0,0 +1,14 @@ +name: 'Reindex' + +on: + release: + types: [prereleased,released] + +jobs: + reindex: + name: 'Reindex updates' + runs-on: [self-hosted,FlipperZeroShell] + steps: + - name: Trigger reindex + run: | + curl -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }} diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml new file mode 100644 index 000000000..ac3fc3684 --- /dev/null +++ b/.github/workflows/unit_tests.yml @@ -0,0 +1,66 @@ +name: 'Unit tests' + +on: + pull_request: + +env: + TARGETS: f7 + DEFAULT_TARGET: f7 + FBT_TOOLCHAIN_PATH: /opt + +jobs: + run_units_on_bench: + runs-on: [self-hosted, FlipperZeroTest] + 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)" + fi + + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + + - name: 'Get flipper from device manager (mock)' + id: device + run: | + echo "flipper=/dev/ttyACM0" >> $GITHUB_OUTPUT + + - name: 'Flash unit tests firmware' + id: flashing + if: success() + run: | + ./fbt flash OPENOCD_ADAPTER_SERIAL=2A0906016415303030303032 FIRMWARE_APP_SET=unit_tests FORCE=1 + + - name: 'Wait for flipper and format ext' + id: format_ext + if: steps.flashing.outcome == 'success' + run: | + source scripts/toolchain/fbtenv.sh + python3 scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}} + python3 scripts/storage.py -p ${{steps.device.outputs.flipper}} format_ext + + - name: 'Copy assets and unit data, reboot and wait for flipper' + id: copy + if: steps.format_ext.outcome == 'success' + run: | + source scripts/toolchain/fbtenv.sh + python3 scripts/storage.py -p ${{steps.device.outputs.flipper}} -f send assets/resources /ext + python3 scripts/storage.py -p ${{steps.device.outputs.flipper}} -f send assets/unit_tests /ext/unit_tests + python3 scripts/power.py -p ${{steps.device.outputs.flipper}} reboot + python3 scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}} + + - name: 'Run units and validate results' + id: run_units + if: steps.copy.outcome == 'success' + run: | + source scripts/toolchain/fbtenv.sh + python3 scripts/testing/units.py ${{steps.device.outputs.flipper}} + + - name: 'Check GDB output' + if: failure() + run: | + ./fbt gdb_trace_all OPENOCD_ADAPTER_SERIAL=2A0906016415303030303032 FIRMWARE_APP_SET=unit_tests FORCE=1 diff --git a/.github/workflows/updater_test.yml b/.github/workflows/updater_test.yml new file mode 100644 index 000000000..d4ca56fad --- /dev/null +++ b/.github/workflows/updater_test.yml @@ -0,0 +1,77 @@ +name: 'Updater test' + +on: + pull_request: + +env: + TARGETS: f7 + DEFAULT_TARGET: f7 + FBT_TOOLCHAIN_PATH: /opt + +jobs: + test_updater_on_bench: + runs-on: [self-hosted, FlipperZeroTest] # currently on same bench as units, needs different bench + 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)" + fi + + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + + - name: 'Get flipper from device manager (mock)' + id: device + run: | + echo "flipper=/dev/ttyACM0" >> $GITHUB_OUTPUT + + - name: 'Flashing target firmware' + id: first_full_flash + run: | + source scripts/toolchain/fbtenv.sh + ./fbt flash_usb_full PORT=${{steps.device.outputs.flipper}} FORCE=1 + python3 scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}} + + - name: 'Validating updater' + id: second_full_flash + if: success() + run: | + source scripts/toolchain/fbtenv.sh + ./fbt flash_usb PORT=${{steps.device.outputs.flipper}} FORCE=1 + python3 scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}} + + - name: 'Get last release tag' + id: release_tag + if: failure() + run: | + echo "tag=$(git tag -l --sort=-version:refname | grep -v "rc\|RC" | head -1)" >> $GITHUB_OUTPUT + + - name: 'Decontaminate previous build leftovers' + if: failure() + run: | + if [ -d .git ]; then + git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)" + fi + + - name: 'Checkout latest release' + uses: actions/checkout@v3 + if: failure() + with: + fetch-depth: 0 + ref: ${{ steps.release_tag.outputs.tag }} + + - name: 'Flash last release' + if: failure() + run: | + ./fbt flash OPENOCD_ADAPTER_SERIAL=2A0906016415303030303032 FORCE=1 + + - name: 'Wait for flipper and format ext' + if: failure() + run: | + source scripts/toolchain/fbtenv.sh + python3 scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}} + python3 scripts/storage.py -p ${{steps.device.outputs.flipper}} format_ext diff --git a/assets/resources/nfc/assets/mf_classic_dict.nfc b/assets/resources/nfc/assets/mf_classic_dict.nfc index ecb2c54dd..d62d0655b 100644 --- a/assets/resources/nfc/assets/mf_classic_dict.nfc +++ b/assets/resources/nfc/assets/mf_classic_dict.nfc @@ -1,31 +1,41 @@ ########################### # Do not edit, this file will be overwritten after firmware update # Use the user_dict file for user keys -# Last update 19th October, 2022 +# Last updated 25 January 2023 # ------------------------- + # MIFARE DEFAULT KEYS # -- ICEMAN FORK VERSION -- # -- CONTRIBUTE TO THIS LIST, SHARING IS CARING -- # https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/mfc_default_keys.dic + # DEFAULTKEY(FIRSTKEYUSEDBYPROGRAMIFNOUSERDEFINEDKEY) FFFFFFFFFFFF + # BLANKKEY 000000000000 + # NFC FORUM MADKEY # MAD ACCESS KEY A (REVERSED) A5A4A3A2A1A0 + # MAD ACCESS KEY B 89ECA97F8C2A + # KEY A WIEN # KEY B WIEN + # ICOPY-X E00000000000 E7D6064C5860 B27CCAB30DBD + # LIB / NAT BIEB D2ECE8B9395E + # NSCP DEFAULT KEY 1494E81663D7 + # KIEV KEYS 569369C5A0E5 632193BE1C3C @@ -34,40 +44,52 @@ D2ECE8B9395E 9DE89E070277 EFF603E1EFE9 F14EE7CAE863 + # KIEV / OV-CHIPKAART B5FF67CBA951 + # RKF # VÄSTTRAFIKEN KEYA, RKF ÖSTGÖTATRAFIKEN KEYA FC00018778F7 0297927C0F77 54726176656C + # VÄSTTRAFIKEN KEYB 00000FFE2488 776974687573 EE0042F88840 + # RKF SLKEYA 26940B21FF5D A64598A77478 + # RKF SLKEYB 5C598C9C58B5 E4D2770A89BE + # RKF REJSKORTDANMARK KEYA 722BFCC5375F F1D83F964314 + # RKF JOJOPRIVAKEYA 505249564141 + # RKF JOJOPRIVAKEYB 505249564142 + # RKF JOJOGROUPKEYA 47524F555041 + # RKF JOJOGROUPKEYB 47524F555042 434F4D4D4F41 434F4D4D4F42 4B0B20107CCB + # TNP3XXX # ACCESS CONTROL SYSTEM 605F5E5D5C5B + # MORE KEYS FROM MFC_DEFAULT_KEYS.LUA 000000000001 000000000002 @@ -82,8 +104,10 @@ F1D83F964314 200000000000 222222222222 27DD91F1FCF1 + # DIRECTORYANDEVENTLOGKEYB 2BA9621E0A36 + # DIRECTORYANDEVENTLOGKEYA 4AF9D7ADEBE4 333333333333 @@ -104,6 +128,7 @@ A00000000000 A053A292A4AF A94133013401 AAAAAAAAAAAA + # KEYFROMLADYADA.NET B00000000000 B127C6F41436 @@ -113,31 +138,41 @@ C934FE34D934 CCCCCCCCCCCC DDDDDDDDDDDD EEEEEEEEEEEE + # ELEVATOR # DATA FROM FORUM FFFFFF545846 F1A97341A9FC + # HOTEL SYSTEM 44AB09010845 85FED980EA5A + # ARD (FR) KEY A 43454952534E + # ARD (FR) KEY B 4A2B29111213 4143414F5250 + # TEHRAN RAILWAY A9B43414F585 1FB235AC1388 + # DATA FROM HTTP://IRQ5.IO/2013/04/13/DECODING-BCARD-CONFERENCE-BADGES/ # BCARD KEYB F4A9EF2AFC6D + # DATA FROM ... # S0 B 89EAC97F8C2A + # S4 A 43C7600DEE6B + # S6 A 0120BF672A64 + # S6 B FB0B20DF1F34 A9F953DEF0A3 @@ -146,6 +181,7 @@ A9F953DEF0A3 21EDF95E7433 C121FF19F681 3D5D9996359A + # HERE BE BIP KEYS... 3A42F33AF429 1FC235AC1309 @@ -179,32 +215,41 @@ D49E2826664F 51284C3686A6 3DF14C8000A1 6A470D54127C + # DATA FROM HTTP://PASTEBIN.COM/AK9BFTPW # LÄNSTRAFIKEN I VÄSTERBOTTEN 48FFE71294A0 E3429281EFC1 16F21A82EC84 460722122510 + # 3DPRINTER # EPI ENVISIONTE 3DPRINTER AAFB06045877 + # GYM # FYSIKEN A 3E65E4FB65B3 + # FYSIKEN B 25094DF6F148 + # CLEVERFIT A05DBD98E0FC + # HOTEL KEYCARD D3B595E9DD63 AFBECD121004 + # SIMONSVOSS 6471A5EF2D1A + # ID06 4E3552426B32 22BDACF5A33F 6E7747394E63 763958704B78 + # 24-7 D21762B2DE3B 0E83A374B513 @@ -218,8 +263,10 @@ F101622750B7 710732200D34 7C335FB121B5 B39AE17435DC + # KEY A 454841585443 + # DATA FROM HTTP://PASTEBIN.COM/GQ6NK38G D39BB83F5297 85675B200017 @@ -245,9 +292,11 @@ FEE470A4CB58 75EDE6A84460 DF27A8F1CB8E B0C9DD55DD4D + # DATA FROM HTTP://BIT.LY/1BDSBJL A0B0C0D0E0F0 A1B1C1D1E1F1 + # DATA FROM MSK SOCIAL A229E68AD9E5 49C2B5296EF4 @@ -274,6 +323,7 @@ C7C0ADB3284F D8A274B2E026 B20B83CB145C 9AFA6CB4FC3D + # DATA FROM HTTP://PASTEBIN.COM/RRJUEDCM 0D258FE90296 E55A3CA71826 @@ -287,16 +337,19 @@ EEB420209D0C 1ACC3189578C C2B7EC7D4EB1 369A4663ACD2 + # DATA FROM HTTPS://GITHUB.COM/ZHANGJINGYE03/ZXCARDUMPER # ZXCARD KEY A/B 668770666644 003003003003 + # DATA FROM HTTP://PHREAKERCLUB.COM/FORUM/SHOWTHREAD.PHP?P=41266 26973EA74321 71F3A315AD26 51044EFB5AAB AC70CA327A04 EB0A8FF88ADE + # TRANSPORT SYSTEM METROMONEY 2803BCB0C7E1 9C616585E26D @@ -305,6 +358,7 @@ EB0A8FF88ADE A160FCD5EC4C 112233445566 361A62F35BC9 + # TRANSPORT SYSTEM SPAIN 83F3CB98C258 070D486BC555 @@ -338,14 +392,18 @@ C52876869800 5145C34DBA19 25352912CD8D 81B20C274C3F + # DATA FROM MALL # PLAYLAND BALIKESIR ABBA1234FCB0 + # A TRIO BOWLING BAHCELIEVLER 314F495254FF 4152414B4E41 + # KARINCA PARK NIGDE 4E474434FFFF + # DATA FROM HTTPS://GITHUB.COM/RADIOWAR/NFCGUI 44DD5A385AAF 21A600056CB0 @@ -383,10 +441,12 @@ CBA6AE869AD5 A7ABBC77CC9E F792C4C76A5C BFB6796A11DB + # DATA FROM SALTO A/B 6A1987C40A21 7F33625BC129 2338B4913111 + # DATA FROM STOYE CB779C50E1BD A27D3804C259 @@ -414,16 +474,22 @@ D9A37831DCE5 C5CFE06D9EA3 C0DECE673829 A56C2DF9A26D + # DATA FROM HTTPS://PASTEBIN.COM/VBWAST74 68D3F7307C89 + # SMART RIDER. WESTERN AUSTRALIAN PUBLIC TRANSPORT CARDS 568C9083F71C + # BANGKOK METRO KEY 97F5DA640B18 + # METRO VALENCIA KEY A8844B0BCA06 + # HTC EINDHOVEN KEY 857464D3AAD1 + # VIGIK KEYS # VARIOUS SOURCES : # * HTTPS://GITHUB.COM/DUMPDOS/VIGIK @@ -432,18 +498,24 @@ A8844B0BCA06 # FRENCH VIGIK # VIGIK1 A 314B49474956 + # VIGIK1 B 564C505F4D41 BA5B895DA162 + # VIGIK MYSTERY KEYS MIFARE 1K EV1 (S50) # 16 A 5C8FF9990DA2 + # 17 A 75CCB59C9BED + # 16 B D01AFEEB890A + # 17 B 4B791BEA7BCC + # BTCINO UNDETERMINED SPREAKD 0X01->0X13 KEY 021209197591 2EF720F2AF76 @@ -452,6 +524,7 @@ D01AFEEB890A 4A6352684677 BF1F4424AF76 536653644C65 + # INTRATONE COGELEC # DATA FROM HTTP://BOUZDECK.COM/RFID/32-CLONING-A-MIFARE-CLASSIC-1K-TAG.HTML 484558414354 @@ -470,6 +543,7 @@ E64A986A5D94 66D2B7DC39EF 6BC1E1AE547D 22729A9BD40F + # DATA FROM HTTPS://DFIR.LU/BLOG/CLONING-A-MIFARE-CLASSIC-1K-TAG.HTML 925B158F796F FAD63ECB5891 @@ -485,8 +559,10 @@ CC6B3B3CD263 703140FD6D86 157C9A513FA5 E2A5DC8E066F + # DATA FROM FORUM, SCHLAGE 9691T FOB EF1232AB18A0 + # DATA FROM A OYSTER CARD 374BF468607F BFC8E353AF63 @@ -517,8 +593,10 @@ A2ABB693CE34 91F93A5564C9 E10623E7A016 B725F9CBF183 + # DATA FROM FDI TAG 8829DA9DAF76 + # DATA FROM GITHUB ISSUE 0A7932DC7E65 11428B5BCE06 @@ -543,14 +621,18 @@ D4FE03CE5B09 D4FE03CE5B0A D4FE03CE5B0F E241E8AFCBAF + # DATA FROM FORUM POST 123F8888F322 050908080008 + # DATA FROM HOIST 4F9F59C9C875 + # DATA FROM PASTEBIN 66F3ED00FED7 F7A39753D018 + # DATA FROM HTTPS://PASTEBIN.COM/Z7PEEZIF 386B4D634A65 666E564F4A44 @@ -582,19 +664,23 @@ F7A39753D018 6F506F493353 31646241686C 77646B633657 + # DATA FROM TRANSPERT 2031D1E57A3B 53C11F90822A 9189449EA24E + # DATA FROM GITHUB 410B9B40B872 2CB1A90071C8 + # DATA FROM 8697389ACA26 1AB23CD45EF6 013889343891 0000000018DE 16DDCB6B3F24 + # DATA FROM HTTPS://PASTEBIN.COM/VWDRZW7D # VINGCARD MIFARE 4K STAFF CARD EC0A9B1A9E06 @@ -608,6 +694,7 @@ B66AC040203A 2E641D99AD5B AD4FB33388BF 69FB7B7CD8EE + # HOTEL 2A6D9205E7CA 2A2C13CC242A @@ -615,25 +702,34 @@ AD4FB33388BF 01FA3FC68349 6D44B5AAF464 1717E34A7A8A + # RFIDEAS 6B6579737472 + # HID MIFARE CLASSIC 1K KEY 484944204953 204752454154 + # HID MIFARE SO 3B7E4FD575AD 11496F97752A + # LUXEO/AZTEK CASHLESS VENDING 415A54454B4D + # BQT 321958042333 + # APERIO KEY_A SECTOR 1, 12, 13, 14, 15 DATA START 0 LENGTH 48 160A91D29A9C + # GALLAGHER B7BF0C13066E + # PIK COMFORT MOSCOW KEYS (ISBC MIFARE PLUS SE 1K) 009FB42D98ED 002E626E2820 + # BOSTON, MA, USA TRANSIT - MBTA CHARLIE CARD # CHARLIE 3060206F5B0A @@ -670,8 +766,10 @@ D80511FC2AB4 BB467463ACD6 E67C8010502D FF58BA1B4478 + # DATA FROM HTTPS://PASTEBIN.COM/KZ8XP4EV FBF225DC5D58 + # DATA HTTPS://PASTEBIN.COM/BEM6BDAE # VINGCARD.TXT 4708111C8604 @@ -688,16 +786,19 @@ FBF225DC5D58 D9BCDE7FC489 0C03A720F208 6018522FAC02 + # DATA FROM HTTPS://PASTEBIN.COM/4T2YFMGT # MIFARE TECHNISCHE UNIVERSITÄT GRAZ TUG D58660D1ACDE 50A11381502C C01FC822C6E5 0854BF31111E + # MORE KEYS: 8A19D40CF2B5 AE8587108640 135B88A94B8B + # RUSSIAN TROIKA CARD 08B386463229 0E8F64340BA4 @@ -753,6 +854,7 @@ EAAC88E5DC99 F8493407799D 6B8BD9860763 D3A297DC2698 + # KEYS FROM MIFARECLASSICTOOL PROJECT 044CE1872BC3 045CECA15535 @@ -808,22 +910,28 @@ FD8705E721B0 00ADA2CD516D 237A4D0D9119 0ED7846C2BC9 + # HOTEL ADINA 9EBC3EB37130 + # MOST LIKELY DIVERSED INDIVIDUAL KEYS. # DATA FROM HTTPS://GITHUB.COM/KORSEHINDI/PROXMARK3/COMMIT/24FDBFA9A1D5C996AAA5C192BC07E4AB28DB4C5C 491CDC863104 A2F63A485632 98631ED2B229 19F1FFE02563 + # ARGENTINA 563A22C01FC8 43CA22C13091 25094DF2C1BD + # OMNITEC.ES HOTEL TIMECARD / MAINTENANCECARD AFBECD120454 + # OMNITEC.ES HOTEL EMERGENCYCARD 842146108088 + # TAPCARD PUBLIC TRANSPORT LA EA1B88DF0A76 D1991E71E2C5 @@ -857,6 +965,7 @@ B81846F06EDF C6A76CB2F3B5 E3AD9E9BA5D4 6C9EC046C1A4 + # ROC HIGHSCHOOL ACCESSCARD B021669B44BB B18CDCDE52B7 @@ -888,6 +997,7 @@ AE43F36C1A9A BE7C4F6C7A9A 5EC7938F140A 82D58AA49CCB + # MELONCARD 323334353637 CEE3632EEFF5 @@ -904,6 +1014,7 @@ A7FB4824ACBF 00F0BD116D70 4CFF128FA3EF 10F3BEBC01DF + # TRANSPORTES INSULAR LA PALMA 0172066B2F03 0000085F0000 @@ -937,6 +1048,7 @@ B1A862985913 3B0172066B2F 3F1A87298691 F3F0172066B2 + # TEHRAN EZPAY 38A88AEC1C43 CBD2568BC7C6 @@ -953,10 +1065,12 @@ D3B1C7EA5C53 604AC8D87C7E 8E7B29460F12 BB3D7B11D224 + # CHACO B210CFA436D2 B8B1CFA646A8 A9F95891F0A4 + # KEYS FROM APK APPLICATION "SCAN BADGE" 4A4C474F524D 444156494442 @@ -976,6 +1090,7 @@ A0004A000036 DFE73BE48AC6 B069D0D03D17 000131B93F28 + # FROM THE DFW AREA, TX, USA A506370E7C0F 26396F2042E7 @@ -992,6 +1107,7 @@ EF4C5A7AC6FC B47058139187 8268046CD154 67CC03B7D577 + # FROM THE HTL MÖDLING, NÖ, AT A5524645CD91 D964406E67B4 @@ -1000,32 +1116,40 @@ D964406E67B4 C27D999912EA 66A163BA82B4 4C60F4B15BA8 + # CAFE + CO, AT 35D850D10A24 4B511F4D28DD E45230E7A9E8 535F47D35E39 FB6C88B7E279 + # METRO CARD, AT 223C3427108A + # UNKNOWN, AT 23D4CDFF8DA3 E6849FCC324B 12FD3A94DF0E 0B83797A9C64 39AD2963D3D1 + # HOTEL BERLIN CLASSIC ROOM A KEY 34B16CD59FF8 + # HOTEL BERLIN CLASSIC ROOM B KEY BB2C0007D022 + # COINMATIC LAUNDRY SMART CARD # DATA FROM: HTTPS://PASTEBIN.COM/XZQILTUF 0734BFB93DAB 85A438F72A8A + # DATA FROM FORUM, CHINESE HOTEL 58AC17BF3629 B62307B62307 A2A3CCA2A3CC + # GRANADA, ES TRANSPORT CARD 000000270000 0F385FFB6529 @@ -1043,6 +1167,7 @@ B385EFA64290 C9739233861F F3864FCCA693 FC9839273862 + # VARIOUS HOTEL KEYS 34D3C568B348 91FF18E63887 @@ -1050,6 +1175,7 @@ FC9839273862 354A787087F1 4A306E62E9B6 B9C874AE63D0 + # DATA FROM OFFICIAL REPO F00DFEEDD0D0 0BB31DC123E5 @@ -1067,18 +1193,23 @@ B8937130B6BA D7744A1A0C44 82908B57EF4F FE04ECFE5577 + # COMFORT INN HOTEL 4D57414C5648 4D48414C5648 + # UNKNOWN HOTEL KEY 6D9B485A4845 + # BOSCH SOLUTION 6000 # FOUND IN TAGINFO APP # RATB KEY C1E51C63B8F5 1DB710648A65 + # E-GO CARD KEY 18F34C92A56E + # LIBRARY CARD MFP - SL1 4A832584637D CA679D6291B0 @@ -1094,6 +1225,7 @@ AADE86B1F9C1 C67BEB41FFBF B84D52971107 52B0D3F6116E + # DATA FROM HTTPS://PASTEBIN.COM/CLSQQ9XN CA3A24669D45 4087C6A75A96 @@ -1102,10 +1234,12 @@ D73438698EEA 5F31F6FCD3A0 A0974382C4C5 A82045A10949 + # DATA FROM HTTPS://PASTEBIN.COM/2IV8H93H # FUNNIVARIUM # FORUM ANKARA 2602FFFFFFFF + # MACERA ADASI # ANKARA KENTPARK # INACTIVE @@ -1113,16 +1247,20 @@ A82045A10949 DFF293979FA7 4D6F62692E45 4118D7EF0902 + # PETROL OFISI # POSITIVE CARD # ODE-GEC 0406080A0C0E + # KONYA ELKART 988ACDECDFB0 120D00FFFFFF + # BOWLINGO # SERDIVAN AVYM 4AE23A562A80 + # KART54 2AFFD6F88B97 A9F3F289B70C @@ -1131,18 +1269,23 @@ DB6819558A25 B16B2E573235 42EF7BF572AB 274E6101FC5E + # CRAZY PARK # KIZILAY AVM 00DD300F4F10 + # KARTSISTEM B FEE2A3FBC5B6 + # TORU ENT # TAURUS AVM 005078565703 + # VING? 0602721E8F06 FC0B50AF8700 F7BA51A9434E + # ESKART # ESKISEHIR TRANSPORT CARD E902395C1744 @@ -1151,6 +1294,7 @@ E902395C1744 D8BA1AA9ABA0 76939DDD9E97 3BF391815A8D + # MUZEKART # MUSEUM CARD FOR TURKEY 7C87013A648A @@ -1182,6 +1326,7 @@ D0DDDF2933EC 240F0BB84681 9E7168064993 2F8A867B06B4 + # BURSAKART # BURSA TRANSPORT CARD 755D49191A78 @@ -1191,18 +1336,22 @@ DAC7E0CBA8FD 0860318A3A89 1927A45A83D3 B2FE3B2875A6 + # PLAYLAND # MALTEPE PARK ABCC1276FCB0 AABAFFCC7612 + # LUNASAN # KOCAELI FAIR 26107E7006A0 + # GAMEFACTORY # OZDILEK 17D071403C20 534F4C415249 534F4C303232 + # NESPRESSO, SMART CARD # KEY-GEN ALGO, THESE KEYS ARE FOR ONE CARD FF9A84635BD2 @@ -1281,15 +1430,20 @@ AE76242931F1 124578ABFEDC ABFEDC124578 4578ABFEDC12 + # PREMIER INN HOTEL CHAIN 5E594208EF02 AF9E38D36582 + # NORWEGIAN BUILDING SITE IDENTICATION CARD. (HMS KORT) 10DF4D1859C8 + # KEY B B5244E79B0C8 + # UKRAINE HOTEL F5C1C4C5DE34 + # DATA FROM MIFARE CLASSIC TOOL REPO # ROTTERDAM UNIVERSITY OF APPLIED SCIENCES CAMPUS CARD BB7923232725 @@ -1314,6 +1468,7 @@ B5ADEFCA46C4 BF3FE47637EC B290401B0CAD AD11006B0601 + # ARMENIAN METRO E4410EF8ED2D 6A68A7D83E11 @@ -1323,6 +1478,7 @@ D3F3B958B8A3 2196FAD8115B 7C469FE86855 CE99FBC8BD26 + # KEYS FROM EUROTHERMES GROUP (SWITZERLAND) D66D91829013 75B691829013 @@ -1338,9 +1494,11 @@ FED791829013 29A791829013 668091829013 00008627C10A + # KEYS FROM NSP MANCHESTER UNIVERSITY UK ACCOMODATION STAFF AND STUDENTS 199404281970 199404281998 + # EASYCARD 310D51E539CA 2CCDA1358323 @@ -1348,6 +1506,7 @@ FED791829013 562E6EF73DB6 F53E9F4114A9 AD38C17DE7D2 + # SOME KEYS OF HTTPS://W3BSIT3-DNS.COM AND HTTPS://IKEY.RU # STRELKA EXTENSION 5C83859F2224 @@ -1358,6 +1517,7 @@ C4D3911AD1B3 CAD7D4A6A996 DA898ACBB854 FEA1295774F9 + # MOSCOW PUBLIC TOILETS CARD 807119F81418 22C8BCD10AAA @@ -1367,6 +1527,7 @@ DBF9F79AB7A2 34EDE51B4C22 C8BCD10AAABA BCD10AAABA42 + # MOSCOW SOCIAL CARD 2F87F74090D1 E53EAEFE478F @@ -1409,10 +1570,12 @@ F750C0095199 82DA4B93DB1C 9CF46DB5FD46 93EB64ACF43D + # KEYS FROM RFIDRESEARCHGROUP PROXMARK3 PROJECT # HTTPS://GITHUB.COM/RFIDRESEARCHGROUP/PROXMARK3/BLOB/MASTER/CLIENT/DICTIONARIES/MFC_DEFAULT_KEYS.DIC 13B91C226E56 5A7A52D5E20D + # IRON LOGIC A3A26EF4C6B0 2C3FEAAE99FC @@ -1431,9 +1594,11 @@ DEC0CEB0CE24 413BED2AE45B D6261A9A4B3F CB9D507CE56D + # MORE KEYS FROM THE PM3 REPO # KEYS OF ARMENIAN UNDERGROUND TICKET A0A1A2A8A4A5 + # https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/mfc_keys_bmp_sorted.dic 002DE0301481 004173272D18 @@ -2435,6 +2600,7 @@ EE17C426D25E EE487A4C806E EE5931913A8D EED56840AEBA + # https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/mfc_keys_icbmp_sorted.dic 00383D96411D 005307DB7853 @@ -3436,6 +3602,7 @@ EE3029556CEB EE49610E6121 EEB704D69BCA EED69A391464 + # https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/mfc_keys_mrzd_sorted.dic 010203040506 013940233313 @@ -3494,6 +3661,7 @@ F83466888612 F89C86B2A961 FFFFAE82366C FFFFD06F83E3 + # Unknown origin 2DEB57A3EA8F 32C1BB023F87 @@ -3577,27 +3745,26 @@ D27058C6E2C7 E19504C39461 FA1FBB3F0F1F FF16014FEFC7 -# + # Cracked by UberGuidoZ # https://github.com/UberGuidoZ -# # BadgeMaker Leaked 1A1B1C1D1E1F 1665FE2AE945 158B51947A8E -E167EC67C7FF -D537320FF9OE +EL67EC67C7FF +D53732OFF9OE 5E56BFA9E2C9 F81CED821B63 C81584EF5EDF 9551F8F9259D -36E1765CE3E8 +36EL765CE3E8 509052C8E42E 776C9B03BE71 -C608E13ADD50 +C608EL3ADD50 BEE8B345B949 -ED0EC56EEFDD -9716D5241E28 +EDOEC56EEFDD +9716D524LE28 05D1FC14DC31 3321FB75A356 F22A78E29880 @@ -3611,9 +3778,9 @@ DB32A6811327 8AA8544A2207 8C5819E780A4 7549E90353A2 -2E52ABE0CE95 +2E52ABEOCE95 E46210ED98AB -61D030C0D7A8 +61DO30COD7A8 18E20102821E DA59354DFB88 040047C12B75 @@ -3622,6 +3789,7 @@ D10008074A6F 446176696453 6F6674776172 6520446F7665 + # Apartment keyfobs in USA from Corvette830 E60F8387F0B9 FFD46FF6C5EE @@ -3630,6 +3798,7 @@ FFD46FF6C5EE 1C5179C4A8A1 16CA203B811B 11AC8C8F3AF2 + # The Westin Jakarta Indonesia from D4DB0D # Peppers Hotel Unknown location from D4DB0D 6E0DD4136B0A @@ -3644,15 +3813,19 @@ FC5AC7678BE3 F09BB8DD142D B4B3FFEDBE0A 540E0D2D1D08 + # Schlage 9691T Keyfob 7579B671051A 4F4553746B41 + # FOOD REPUBLIC 30C1DC9DD040 A9B9C1D0E3F1 + # iGuard Simple (and reverse) keys AAAAAAFFFFFF FFFFFFAAAAAA + # Vigik verified by quantum-x # https://github.com/RfidResearchGroup/proxmark3/pull/1742#issuecomment-1206113976 A00027000099 @@ -3670,19 +3843,20 @@ A00000043D79 A00000000064 A00025000030 A00003000057 -# + # BH USA 2013 conference 012279BAD3E5 + # Vigik ScanBadge App (fr.badgevigik.scanbadge) # Website https://badge-vigik.fr/ - By Alex` 0000A2B3C86F -021200c20307 +021200C20307 021209197507 1E34B127AF9C 303041534956 4143532D494E 41454E521985 -43412d627400 +43412D627400 455249524345 456666456666 45B722C63319 @@ -3701,10 +3875,12 @@ A00003000057 9EB7C8A6D4E3 A22AE12C9013 AFC984A3576E + # Spackular A/B # data from http://www.proxmark.org/forum/viewtopic.php?pid=45100#p45100 7CB033257498 1153AABAFF6C + # iGuard Simple and Reverse Keys D537320FF90E 36E1765CE3E8 @@ -3713,10 +3889,13 @@ ED0EC56EEFDD 9716D5241E28 2E52ABE0CE95 61D030C0D7A8 + # BadgeMaker Leaked from https://github.com/UberGuidoZ E167EC67C7FF + # Schlage 9691T Keyfob from seasnaill Added by VideoMan. 3111A3A303EB + # Transport cards E954024EE754 0CD464CDC100 @@ -3724,17 +3903,13 @@ BC305FE2DA65 CF0EC6ACF2F9 F7A545095C49 6862FD600F78 -#MISC KEYS -36El765CE3E8 -9716D524lE28 -C608El3ADD50 -El67EC67C7FF -# keys for transport cards by novacard.ru 72A0C485D3F7 6A530C91F85B + # RENFE MADRID (TRAIN) Extracted with detect reader 701AA491A4A5 12BA20088ED3 + # MISC KEYS FROM MY OLD ACCESS CARDS F18D91EE3033 0E726E11CFCC @@ -3784,3 +3959,80 @@ E10F0E7A8DD5 F833E24C3F1C FA8CA10C7D59 FE98F38F3EE2 +# +########################################## +# added by colonelborkmundus +# "the more, the marriott" mifare project +# + +# 1k - graduate hotel +C49DAE1C6049 +209A2B910545 + +# 1k - westin +8C29F8320617 +5697519A8F02 +7D0A1C277C05 +2058580A941F +C40964215509 +D44CFC178460 + +# 1k - marriott +7B4DFC6D6525 +23C9FDD9A366 +3119A70628EB +30AAD6A711EF +1330824CD356 +43012BD9EB87 +035C70558D7B +9966588CB9A0 +12AB4C37BB8B + +# 1k - AC hotels marriott +8EA8EC3F2320 +7B56B2B38725 + +# 1k - the ritz-carlton +30FB20D0EFEF +D20289CD9E6E +66A3B064CC4B +D18296CD9E6E + +# 1k - unknown +722538817225 + +# 1k - aria resort & casino +316B8FAA12EF +A18D9F4E75AF + +# 1k - fairfield inn & suites marriott +7AEB989A5525 +7B3B589A5525 +215E9DED9DDF +334E91BE3377 +310308EC52EF + +# 1k - residence inn marriott +F72CD208FDF9 + +# 1k - sheraton +42FC522DE987 + +# 1k - millenium hotels +132F641C948B + +# 1k - moxy hotels +20C166C00ADB +9EE3896C4530 + +# 1k - residence inn marriott +3122AE5341EB + +# 1k - americinn +8AC04C1A4A25 + +# 1k - the industrialist +2158E314C3DF + +# 1k - waldorf astoria +011C6CF459E8 \ No newline at end of file From b0c12822d210a037234c0a185ced7e1e14a4a239 Mon Sep 17 00:00:00 2001 From: Clara K Date: Fri, 27 Jan 2023 00:21:26 +0100 Subject: [PATCH 05/26] Update ReadMe.md --- ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index 60c5f54d6..9ab83205d 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -7,7 +7,7 @@ [Intro](https://github.com/ClaraCrazy/Flipper-Xtreme#What-makes-it-special) | [Animations](https://github.com/ClaraCrazy/Flipper-Xtreme#Animations--Asset-Packs) | [Docs](https://github.com/ClaraCrazy/Flipper-Xtreme/wiki) | [Changelog](https://github.com/ClaraCrazy/Flipper-Xtreme#list-of-changes) | [Known bugs](https://github.com/ClaraCrazy/Flipper-Xtreme#Known-bugs) | [Install](https://github.com/ClaraCrazy/Flipper-Xtreme#Install) | [Build](https://github.com/ClaraCrazy/Flipper-Xtreme#build-it-yourself) | [Discord](https://discord.gg/flipper-xtreme) ----- -This firmware is a complete overhaul of the [Official Firmware](https://github.com/flipperdevices/flipperzero-firmware), it also features some of the badly implemented ideas from RogueMaster, and lots of awesome code-bits from [Unleashed](https://github.com/DarkFlippers/unleashed-firmware). +This firmware is a complete overhaul of the [Official Firmware](https://github.com/flipperdevices/flipperzero-firmware), it also features lots of awesome code-bits from [Unleashed](https://github.com/DarkFlippers/unleashed-firmware). -----
From 5ff8dab68fc7d7dd48868657781db21a6ee8158e Mon Sep 17 00:00:00 2001 From: Clara K Date: Fri, 27 Jan 2023 00:43:28 +0100 Subject: [PATCH 06/26] Update check_submodules.yml --- .github/workflows/check_submodules.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check_submodules.yml b/.github/workflows/check_submodules.yml index 2eb2027c9..d1a1a64c3 100644 --- a/.github/workflows/check_submodules.yml +++ b/.github/workflows/check_submodules.yml @@ -11,7 +11,7 @@ on: jobs: check_protobuf: - runs-on: [self-hosted, FlipperZeroShell] + runs-on: ubuntu-latest steps: - name: 'Decontaminate previous build leftovers' run: | From 1f416ca99aec32b181ca2d189244494e5940fd9a Mon Sep 17 00:00:00 2001 From: Clara K Date: Fri, 27 Jan 2023 00:44:02 +0100 Subject: [PATCH 07/26] Update lint_c.yml --- .github/workflows/lint_c.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint_c.yml b/.github/workflows/lint_c.yml index a6fd5127c..d9d8a267e 100644 --- a/.github/workflows/lint_c.yml +++ b/.github/workflows/lint_c.yml @@ -16,7 +16,7 @@ env: jobs: lint_c_cpp: - runs-on: [self-hosted,FlipperZeroShell] + runs-on: ubuntu-latest steps: - name: 'Decontaminate previous build leftovers' run: | From c47c9b63a70bbcf0f9fda273be1341c904008500 Mon Sep 17 00:00:00 2001 From: Clara K Date: Fri, 27 Jan 2023 00:44:21 +0100 Subject: [PATCH 08/26] Update lint_python.yml --- .github/workflows/lint_python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index 66c36064c..0e96481fc 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -15,7 +15,7 @@ env: jobs: lint_python: - runs-on: [self-hosted,FlipperZeroShell] + runs-on: ubuntu-latest steps: - name: 'Decontaminate previous build leftovers' run: | From beea43d7f6b2f0b7e974f3ba1bb64f563a79c434 Mon Sep 17 00:00:00 2001 From: Clara K Date: Fri, 27 Jan 2023 00:44:52 +0100 Subject: [PATCH 09/26] Delete merge_report.yml --- .github/workflows/merge_report.yml | 45 ------------------------------ 1 file changed, 45 deletions(-) delete mode 100644 .github/workflows/merge_report.yml diff --git a/.github/workflows/merge_report.yml b/.github/workflows/merge_report.yml deleted file mode 100644 index 13fab0948..000000000 --- a/.github/workflows/merge_report.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: 'Check FL ticket in PR name' - -on: - push: - branches: - - dev - -env: - FBT_TOOLCHAIN_PATH: /runner/_work - -jobs: - merge_report: - runs-on: [self-hosted,FlipperZeroShell] - 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)" - fi - - - name: 'Checkout code' - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ github.event.pull_request.head.sha }} - - - name: 'Get commit details' - run: | - if [[ ${{ github.event_name }} == 'pull_request' ]]; then - TYPE="pull" - elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then - TYPE="tag" - else - TYPE="other" - fi - python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE" - - - name: 'Check ticket and report' - run: | - source scripts/toolchain/fbtenv.sh - python3 -m pip install slack_sdk - python3 scripts/merge_report_qa.py \ - ${{ secrets.QA_REPORT_SLACK_TOKEN }} \ - ${{ secrets.QA_REPORT_SLACK_CHANNEL }} - From 82d6f1c19b3066c431e644b0bfabfce94162fe34 Mon Sep 17 00:00:00 2001 From: Clara K Date: Fri, 27 Jan 2023 00:45:03 +0100 Subject: [PATCH 10/26] Delete reindex.yml --- .github/workflows/reindex.yml | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 .github/workflows/reindex.yml diff --git a/.github/workflows/reindex.yml b/.github/workflows/reindex.yml deleted file mode 100644 index ea850e705..000000000 --- a/.github/workflows/reindex.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: 'Reindex' - -on: - release: - types: [prereleased,released] - -jobs: - reindex: - name: 'Reindex updates' - runs-on: [self-hosted,FlipperZeroShell] - steps: - - name: Trigger reindex - run: | - curl -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }} From 6393fac9cdcbbb5817c0f9973760b47b6e3cfdd0 Mon Sep 17 00:00:00 2001 From: Clara K Date: Fri, 27 Jan 2023 00:45:22 +0100 Subject: [PATCH 11/26] Delete unit_tests.yml --- .github/workflows/unit_tests.yml | 66 -------------------------------- 1 file changed, 66 deletions(-) delete mode 100644 .github/workflows/unit_tests.yml diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml deleted file mode 100644 index ac3fc3684..000000000 --- a/.github/workflows/unit_tests.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: 'Unit tests' - -on: - pull_request: - -env: - TARGETS: f7 - DEFAULT_TARGET: f7 - FBT_TOOLCHAIN_PATH: /opt - -jobs: - run_units_on_bench: - runs-on: [self-hosted, FlipperZeroTest] - 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)" - fi - - - name: Checkout code - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ github.event.pull_request.head.sha }} - - - name: 'Get flipper from device manager (mock)' - id: device - run: | - echo "flipper=/dev/ttyACM0" >> $GITHUB_OUTPUT - - - name: 'Flash unit tests firmware' - id: flashing - if: success() - run: | - ./fbt flash OPENOCD_ADAPTER_SERIAL=2A0906016415303030303032 FIRMWARE_APP_SET=unit_tests FORCE=1 - - - name: 'Wait for flipper and format ext' - id: format_ext - if: steps.flashing.outcome == 'success' - run: | - source scripts/toolchain/fbtenv.sh - python3 scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}} - python3 scripts/storage.py -p ${{steps.device.outputs.flipper}} format_ext - - - name: 'Copy assets and unit data, reboot and wait for flipper' - id: copy - if: steps.format_ext.outcome == 'success' - run: | - source scripts/toolchain/fbtenv.sh - python3 scripts/storage.py -p ${{steps.device.outputs.flipper}} -f send assets/resources /ext - python3 scripts/storage.py -p ${{steps.device.outputs.flipper}} -f send assets/unit_tests /ext/unit_tests - python3 scripts/power.py -p ${{steps.device.outputs.flipper}} reboot - python3 scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}} - - - name: 'Run units and validate results' - id: run_units - if: steps.copy.outcome == 'success' - run: | - source scripts/toolchain/fbtenv.sh - python3 scripts/testing/units.py ${{steps.device.outputs.flipper}} - - - name: 'Check GDB output' - if: failure() - run: | - ./fbt gdb_trace_all OPENOCD_ADAPTER_SERIAL=2A0906016415303030303032 FIRMWARE_APP_SET=unit_tests FORCE=1 From 3cbbad20cf9917536da266d413aaedcf29a0c1e8 Mon Sep 17 00:00:00 2001 From: Clara K Date: Fri, 27 Jan 2023 00:45:32 +0100 Subject: [PATCH 12/26] Delete updater_test.yml --- .github/workflows/updater_test.yml | 77 ------------------------------ 1 file changed, 77 deletions(-) delete mode 100644 .github/workflows/updater_test.yml diff --git a/.github/workflows/updater_test.yml b/.github/workflows/updater_test.yml deleted file mode 100644 index d4ca56fad..000000000 --- a/.github/workflows/updater_test.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: 'Updater test' - -on: - pull_request: - -env: - TARGETS: f7 - DEFAULT_TARGET: f7 - FBT_TOOLCHAIN_PATH: /opt - -jobs: - test_updater_on_bench: - runs-on: [self-hosted, FlipperZeroTest] # currently on same bench as units, needs different bench - 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)" - fi - - - name: Checkout code - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ github.event.pull_request.head.sha }} - - - name: 'Get flipper from device manager (mock)' - id: device - run: | - echo "flipper=/dev/ttyACM0" >> $GITHUB_OUTPUT - - - name: 'Flashing target firmware' - id: first_full_flash - run: | - source scripts/toolchain/fbtenv.sh - ./fbt flash_usb_full PORT=${{steps.device.outputs.flipper}} FORCE=1 - python3 scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}} - - - name: 'Validating updater' - id: second_full_flash - if: success() - run: | - source scripts/toolchain/fbtenv.sh - ./fbt flash_usb PORT=${{steps.device.outputs.flipper}} FORCE=1 - python3 scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}} - - - name: 'Get last release tag' - id: release_tag - if: failure() - run: | - echo "tag=$(git tag -l --sort=-version:refname | grep -v "rc\|RC" | head -1)" >> $GITHUB_OUTPUT - - - name: 'Decontaminate previous build leftovers' - if: failure() - run: | - if [ -d .git ]; then - git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)" - fi - - - name: 'Checkout latest release' - uses: actions/checkout@v3 - if: failure() - with: - fetch-depth: 0 - ref: ${{ steps.release_tag.outputs.tag }} - - - name: 'Flash last release' - if: failure() - run: | - ./fbt flash OPENOCD_ADAPTER_SERIAL=2A0906016415303030303032 FORCE=1 - - - name: 'Wait for flipper and format ext' - if: failure() - run: | - source scripts/toolchain/fbtenv.sh - python3 scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}} - python3 scripts/storage.py -p ${{steps.device.outputs.flipper}} format_ext From a8b5158d583a3ec7d616a6f00b9f85abfc5e1aef Mon Sep 17 00:00:00 2001 From: Clara K Date: Fri, 27 Jan 2023 00:53:16 +0100 Subject: [PATCH 13/26] Delete pvs_studio.yml --- .github/workflows/pvs_studio.yml | 115 ------------------------------- 1 file changed, 115 deletions(-) delete mode 100644 .github/workflows/pvs_studio.yml diff --git a/.github/workflows/pvs_studio.yml b/.github/workflows/pvs_studio.yml deleted file mode 100644 index 46ee8801d..000000000 --- a/.github/workflows/pvs_studio.yml +++ /dev/null @@ -1,115 +0,0 @@ -name: 'Static C/C++ analysis with PVS-Studio' - -on: - push: - branches: - - dev - - "release*" - tags: - - '*' - pull_request: - -env: - TARGETS: f7 - DEFAULT_TARGET: f7 - FBT_TOOLCHAIN_PATH: /runner/_work - -jobs: - analyse_c_cpp: - if: ${{ !github.event.pull_request.head.repo.fork }} - runs-on: [self-hosted, FlipperZeroShell] - 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)" - fi - - - name: 'Checkout code' - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ github.event.pull_request.head.sha }} - - - name: 'Get commit details' - id: names - run: | - if [[ ${{ github.event_name }} == 'pull_request' ]]; then - TYPE="pull" - elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then - TYPE="tag" - else - TYPE="other" - fi - python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE" - - - name: 'Make reports directory' - run: | - rm -rf reports/ - mkdir reports - - - name: 'Generate compile_comands.json' - run: | - ./fbt COMPACT=1 version_json proto_ver icons firmware_cdb dolphin_internal dolphin_blocking _fap_icons api_syms - - - name: 'Static code analysis' - run: | - source scripts/toolchain/fbtenv.sh - pvs-studio-analyzer credentials ${{ secrets.PVS_STUDIO_CREDENTIALS }} - pvs-studio-analyzer analyze \ - @.pvsoptions \ - -C gccarm \ - -j$(grep -c processor /proc/cpuinfo) \ - -f build/f7-firmware-DC/compile_commands.json \ - -o PVS-Studio.log - - - name: 'Convert PVS-Studio output to html and detect warnings' - id: pvs-warn - run: | - WARNINGS=0 - plog-converter \ - -a GA:1,2,3 \ - -t fullhtml \ - --indicate-warnings \ - PVS-Studio.log \ - -o reports/${DEFAULT_TARGET}-${SUFFIX} || WARNINGS=1 - echo "warnings=${WARNINGS}" >> $GITHUB_OUTPUT - - - name: 'Upload artifacts to update server' - if: ${{ !github.event.pull_request.head.repo.fork && (steps.pvs-warn.outputs.warnings != 0) }} - run: | - mkdir -p ~/.ssh - ssh-keyscan -p ${{ secrets.RSYNC_DEPLOY_PORT }} -H ${{ secrets.RSYNC_DEPLOY_HOST }} > ~/.ssh/known_hosts - echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key; - 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/"${BRANCH_NAME}/"; - rm ./deploy_key; - - - name: 'Find Previous Comment' - if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request && (steps.pvs-warn.outputs.warnings != 0) }} - uses: peter-evans/find-comment@v2 - id: fc - with: - issue-number: ${{ github.event.pull_request.number }} - comment-author: 'github-actions[bot]' - body-includes: 'PVS-Studio report for commit' - - - name: 'Create or update comment' - if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request && (steps.pvs-warn.outputs.warnings != 0) }} - uses: peter-evans/create-or-update-comment@v1 - with: - comment-id: ${{ steps.fc.outputs.comment-id }} - issue-number: ${{ github.event.pull_request.number }} - body: | - **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 - - - name: 'Raise exception' - if: ${{ steps.pvs-warn.outputs.warnings != 0 }} - run: | - echo "Please fix all PVS varnings before merge" - exit 1 - From ff9f925e2f88b6fbf7be1515ee7701c9bd77d7e3 Mon Sep 17 00:00:00 2001 From: Clara K Date: Fri, 27 Jan 2023 01:30:08 +0100 Subject: [PATCH 14/26] Update lint_python.yml --- .github/workflows/lint_python.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index 0e96481fc..4b92e0e90 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -10,7 +10,6 @@ on: pull_request: env: - FBT_TOOLCHAIN_PATH: /runner/_work SET_GH_OUTPUT: 1 jobs: From 71ddd0f65eb0e576cd3884ec63a5113796bdcd2a Mon Sep 17 00:00:00 2001 From: Clara K Date: Fri, 27 Jan 2023 01:31:05 +0100 Subject: [PATCH 15/26] Update lint_c.yml --- .github/workflows/lint_c.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/lint_c.yml b/.github/workflows/lint_c.yml index d9d8a267e..232e3c689 100644 --- a/.github/workflows/lint_c.yml +++ b/.github/workflows/lint_c.yml @@ -11,7 +11,6 @@ on: env: TARGETS: f7 - FBT_TOOLCHAIN_PATH: /runner/_work SET_GH_OUTPUT: 1 jobs: From 54a9bfb1db7e57970568304e8d671954614af071 Mon Sep 17 00:00:00 2001 From: Clara K Date: Fri, 27 Jan 2023 01:32:07 +0100 Subject: [PATCH 16/26] Update ReadMe.md --- ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index 9ab83205d..66b961fef 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -23,7 +23,7 @@ The goal of this Firmware is to regularly bring out amazing updates based on wha - Giving the level system a purpose: Right now, each level unlocks a new wallpaper. More on that below -- Clean upgraded code: RM wrote some updates to certain files. These are... painful, to say the least. Here its all built with perfection in mind and integrated in a mostly clean way. I invite you all to compare the code with theirs. +- Clean upgraded code: Some people wrote updates to certain files. These are... painful, to say the least. Here its all built with perfection in mind and integrated in a mostly clean way. I invite you all to compare the code with theirs. - Up2Date: This firmware receives updates from a few repositories, not just from its Upstream. If there are functional, but yet un-merged Pull requests on another flipper firmware that are good, they will be in here! From d9ae5b4cb2277cd4358cc2c3cb39a36144f63583 Mon Sep 17 00:00:00 2001 From: WillyJL Date: Fri, 27 Jan 2023 00:54:51 +0000 Subject: [PATCH 17/26] Begone --- .github/workflows/build.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6344bc846..99f80fefa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,7 +50,6 @@ jobs: mkdir artifacts - name: 'Bundle scripts' - if: ${{ !github.event.pull_request.head.repo.fork }} run: | tar czpf artifacts/flipper-z-any-scripts-${SUFFIX}.tgz scripts debug @@ -63,7 +62,6 @@ jobs: done - name: 'Move upload files' - if: ${{ !github.event.pull_request.head.repo.fork }} run: | set -e for TARGET in ${TARGETS}; do @@ -75,12 +73,10 @@ jobs: git diff --exit-code - name: 'Bundle resources' - if: ${{ !github.event.pull_request.head.repo.fork }} run: | 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: | cp build/core2_firmware.tgz "artifacts/flipper-z-any-core2_firmware-${SUFFIX}.tgz" From 0879f92e3de36799f2e38ca2a539858eff18e7bb Mon Sep 17 00:00:00 2001 From: Clara K Date: Fri, 27 Jan 2023 02:05:01 +0100 Subject: [PATCH 18/26] Update ReadMe.md --- ReadMe.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ReadMe.md b/ReadMe.md index 66b961fef..0a0d2adda 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -39,12 +39,16 @@ You can easily create your own pack, or find some user made ones in the discord
+
+ Once you have some packs, upload them to your Flipper in SD/dolphin_custom (if you did this right you should see SD/dolphin_custom/PackName/Anims and/or SD/dolphin_custom/PackName/Icons).
+
+ After installing the packs to Flipper, hit the Arrow UP button on the main menu and go to Xtreme Settings. Here choose which pack you want and tweak the other settings how you prefer, then press back to reboot and enjoy your new assets & animations! From a2b797fe01e7945e713eac651fb93cc36e87ccb4 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Fri, 27 Jan 2023 02:09:42 +0100 Subject: [PATCH 19/26] formatting --- applications/plugins/dap_link/dap_link.c | 3 +- applications/plugins/dice/dice.c | 1 - .../plugins/orgasmotron/orgasmotron.c | 37 +- applications/plugins/protoview/app.c | 174 ++++----- applications/plugins/protoview/app.h | 266 +++++++------ applications/plugins/protoview/app_subghz.c | 68 ++-- applications/plugins/protoview/crc.c | 9 +- .../plugins/protoview/custom_presets.h | 31 +- applications/plugins/protoview/data_feed.c | 17 +- applications/plugins/protoview/fields.c | 348 +++++++++--------- .../plugins/protoview/protocols/b4b1.c | 67 ++-- .../plugins/protoview/protocols/keeloq.c | 99 +++-- .../plugins/protoview/protocols/oregon2.c | 90 +++-- .../protoview/protocols/tpms/citroen.c | 46 +-- .../plugins/protoview/protocols/tpms/ford.c | 49 ++- .../protoview/protocols/tpms/renault.c | 104 +++--- .../protoview/protocols/tpms/schrader.c | 52 ++- .../protocols/tpms/schrader_eg53ma4.c | 47 ++- .../plugins/protoview/protocols/tpms/toyota.c | 57 ++- applications/plugins/protoview/raw_samples.c | 47 ++- applications/plugins/protoview/raw_samples.h | 27 +- applications/plugins/protoview/signal.c | 348 ++++++++++-------- applications/plugins/protoview/signal_file.c | 96 +++-- applications/plugins/protoview/ui.c | 99 +++-- applications/plugins/protoview/view_build.c | 211 ++++++----- .../plugins/protoview/view_direct_sampling.c | 45 ++- applications/plugins/protoview/view_info.c | 211 ++++++----- .../plugins/protoview/view_raw_signal.c | 76 ++-- .../plugins/protoview/view_settings.c | 74 ++-- applications/plugins/tama_p1/hal.c | 2 +- applications/plugins/tama_p1/tama.h | 1 - applications/plugins/tama_p1/tama_p1.c | 145 ++++---- .../desktop/animations/animation_manager.c | 35 +- .../desktop/animations/animation_storage.c | 9 +- .../desktop/views/desktop_view_lock_menu.c | 2 +- .../services/dolphin/helpers/dolphin_state.c | 7 +- .../services/power/power_service/power.c | 9 +- applications/settings/about/about.c | 19 +- .../settings/dolphin_passport/passport.c | 2 +- .../scenes/xtreme_settings_scene_start.c | 76 ++-- .../settings/xtreme_settings/xtreme_assets.c | 207 +++++++---- .../settings/xtreme_settings/xtreme_assets.h | 7 +- .../xtreme_settings/xtreme_settings.c | 18 +- .../xtreme_settings/xtreme_settings_app.c | 20 +- 44 files changed, 1735 insertions(+), 1623 deletions(-) diff --git a/applications/plugins/dap_link/dap_link.c b/applications/plugins/dap_link/dap_link.c index c46c68788..dd684810a 100644 --- a/applications/plugins/dap_link/dap_link.c +++ b/applications/plugins/dap_link/dap_link.c @@ -486,8 +486,7 @@ int32_t dap_link_app(void* p) { if(furi_hal_usb_is_locked()) { DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); DialogMessage* message = dialog_message_alloc(); - dialog_message_set_header( - message, "Connection\nis active!", 3, 2, AlignLeft, AlignTop); + dialog_message_set_header(message, "Connection\nis active!", 3, 2, AlignLeft, AlignTop); dialog_message_set_text( message, "Disconnect from\nPC or phone to\nuse this function.", diff --git a/applications/plugins/dice/dice.c b/applications/plugins/dice/dice.c index 61aa7b4f5..dc748b68f 100644 --- a/applications/plugins/dice/dice.c +++ b/applications/plugins/dice/dice.c @@ -467,7 +467,6 @@ int32_t dice_app(void* p) { return 255; } - ViewPort* view_port = view_port_alloc(); view_port_draw_callback_set(view_port, dice_render_callback, plugin_state); view_port_input_callback_set(view_port, dice_input_callback, plugin_state->event_queue); diff --git a/applications/plugins/orgasmotron/orgasmotron.c b/applications/plugins/orgasmotron/orgasmotron.c index b28f392f5..684fc3d95 100644 --- a/applications/plugins/orgasmotron/orgasmotron.c +++ b/applications/plugins/orgasmotron/orgasmotron.c @@ -40,7 +40,7 @@ int32_t orgasmotron_app(void* p) { PluginState* plugin_state = malloc(sizeof(PluginState)); ValueMutex state_mutex; - if (!init_mutex(&state_mutex, plugin_state, sizeof(PluginState))) { + if(!init_mutex(&state_mutex, plugin_state, sizeof(PluginState))) { FURI_LOG_E("Orgasmatron", "cannot create mutex\r\n"); free(plugin_state); return 255; @@ -61,10 +61,10 @@ int32_t orgasmotron_app(void* p) { //int mode = 0; bool processing = true; //while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) { - while (processing) { + while(processing) { FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); PluginState* plugin_state = (PluginState*)acquire_mutex_block(&state_mutex); - if (event_status == FuriStatusOk) { + if(event_status == FuriStatusOk) { if(event.key == InputKeyBack && event.type == InputTypeShort) { //Exit Application notification_message(notification, &sequence_reset_vibro); @@ -73,53 +73,58 @@ int32_t orgasmotron_app(void* p) { processing = false; //break; } - if(event.key == InputKeyOk && (event.type == InputTypePress || event.type == InputTypeRelease)) { + if(event.key == InputKeyOk && + (event.type == InputTypePress || event.type == InputTypeRelease)) { plugin_state->mode = 0; } - if(event.key == InputKeyLeft && (event.type == InputTypePress || event.type == InputTypeRelease)) { + if(event.key == InputKeyLeft && + (event.type == InputTypePress || event.type == InputTypeRelease)) { plugin_state->mode = 1; } - if(event.key == InputKeyRight && (event.type == InputTypePress || event.type == InputTypeRelease)) { + if(event.key == InputKeyRight && + (event.type == InputTypePress || event.type == InputTypeRelease)) { plugin_state->mode = 3; } - if(event.key == InputKeyUp && (event.type == InputTypePress || event.type == InputTypeRelease)) { + if(event.key == InputKeyUp && + (event.type == InputTypePress || event.type == InputTypeRelease)) { plugin_state->mode = 2; } - if(event.key == InputKeyDown && (event.type == InputTypePress || event.type == InputTypeRelease)) { + if(event.key == InputKeyDown && + (event.type == InputTypePress || event.type == InputTypeRelease)) { plugin_state->mode = 4; } } - - if (plugin_state->mode == 0) { + + if(plugin_state->mode == 0) { //Stop Vibration notification_message(notification, &sequence_reset_vibro); notification_message(notification, &sequence_reset_green); - } else if (plugin_state->mode == 1) { + } else if(plugin_state->mode == 1) { //Full power notification_message(notification, &sequence_set_vibro_on); notification_message(notification, &sequence_set_green_255); - } else if (plugin_state->mode == 2) { + } else if(plugin_state->mode == 2) { //Pulsed Vibration notification_message(notification, &sequence_set_vibro_on); notification_message(notification, &sequence_set_green_255); delay(100); notification_message(notification, &sequence_reset_vibro); - } else if (plugin_state->mode == 3) { + } else if(plugin_state->mode == 3) { //Soft power notification_message(notification, &sequence_set_vibro_on); notification_message(notification, &sequence_set_green_255); delay(50); notification_message(notification, &sequence_reset_vibro); - } else if (plugin_state->mode == 4) { + } else if(plugin_state->mode == 4) { //Special Sequence - for (int i = 0;i < 15;i++) { + for(int i = 0; i < 15; i++) { notification_message(notification, &sequence_set_vibro_on); notification_message(notification, &sequence_set_green_255); delay(50); notification_message(notification, &sequence_reset_vibro); delay(50); } - for (int i = 0;i < 2;i++) { + for(int i = 0; i < 2; i++) { notification_message(notification, &sequence_set_vibro_on); notification_message(notification, &sequence_set_green_255); delay(400); diff --git a/applications/plugins/protoview/app.c b/applications/plugins/protoview/app.c index f16457e55..d060e2242 100644 --- a/applications/plugins/protoview/app.c +++ b/applications/plugins/protoview/app.c @@ -40,8 +40,8 @@ extern const SubGhzProtocolRegistry protoview_protocol_registry; /* The callback actually just passes the control to the actual active * view callback, after setting up basic stuff like cleaning the screen * and setting color to black. */ -static void render_callback(Canvas *const canvas, void *ctx) { - ProtoViewApp *app = ctx; +static void render_callback(Canvas* const canvas, void* ctx) { + ProtoViewApp* app = ctx; /* Clear screen. */ canvas_set_color(canvas, ColorWhite); @@ -51,14 +51,25 @@ static void render_callback(Canvas *const canvas, void *ctx) { /* Call who is in charge right now. */ switch(app->current_view) { - case ViewRawPulses: render_view_raw_pulses(canvas,app); break; - case ViewInfo: render_view_info(canvas,app); break; + case ViewRawPulses: + render_view_raw_pulses(canvas, app); + break; + case ViewInfo: + render_view_info(canvas, app); + break; case ViewFrequencySettings: case ViewModulationSettings: - render_view_settings(canvas,app); break; - case ViewDirectSampling: render_view_direct_sampling(canvas,app); break; - case ViewBuildMessage: render_view_build_message(canvas,app); break; - default: furi_crash(TAG "Invalid view selected"); break; + render_view_settings(canvas, app); + break; + case ViewDirectSampling: + render_view_direct_sampling(canvas, app); + break; + case ViewBuildMessage: + render_view_build_message(canvas, app); + break; + default: + furi_crash(TAG "Invalid view selected"); + break; } /* Draw the alert box if set. */ @@ -67,10 +78,9 @@ static void render_callback(Canvas *const canvas, void *ctx) { /* Here all we do is putting the events into the queue that will be handled * in the while() loop of the app entry point function. */ -static void input_callback(InputEvent* input_event, void* ctx) -{ - ProtoViewApp *app = ctx; - furi_message_queue_put(app->event_queue,input_event,FuriWaitForever); +static void input_callback(InputEvent* input_event, void* ctx) { + ProtoViewApp* app = ctx; + furi_message_queue_put(app->event_queue, input_event, FuriWaitForever); } /* Called to switch view (when left/right is pressed). Handles @@ -80,15 +90,15 @@ static void input_callback(InputEvent* input_event, void* ctx) * The 'switchto' parameter can be the identifier of a view, or the * special views ViewGoNext and ViewGoPrev in order to move to * the logical next/prev view. */ -static void app_switch_view(ProtoViewApp *app, ProtoViewCurrentView switchto) { +static void app_switch_view(ProtoViewApp* app, ProtoViewCurrentView switchto) { /* Switch to the specified view. */ ProtoViewCurrentView old = app->current_view; - if (switchto == ViewGoNext) { + if(switchto == ViewGoNext) { app->current_view++; - if (app->current_view == ViewLast) app->current_view = 0; - } else if (switchto == ViewGoPrev) { - if (app->current_view == 0) - app->current_view = ViewLast-1; + if(app->current_view == ViewLast) app->current_view = 0; + } else if(switchto == ViewGoPrev) { + if(app->current_view == 0) + app->current_view = ViewLast - 1; else app->current_view--; } else { @@ -103,20 +113,20 @@ static void app_switch_view(ProtoViewApp *app, ProtoViewCurrentView switchto) { /* Reset the view private data each time, before calling the enter/exit * callbacks that may want to setup some state. */ - memset(app->view_privdata,0,PROTOVIEW_VIEW_PRIVDATA_LEN); + memset(app->view_privdata, 0, PROTOVIEW_VIEW_PRIVDATA_LEN); /* Call the enter/exit view callbacks if needed. */ - if (old == ViewDirectSampling) view_exit_direct_sampling(app); - if (new == ViewDirectSampling) view_enter_direct_sampling(app); - if (old == ViewBuildMessage) view_exit_build_message(app); - if (new == ViewBuildMessage) view_enter_build_message(app); - if (old == ViewInfo) view_exit_info(app); + if(old == ViewDirectSampling) view_exit_direct_sampling(app); + if(new == ViewDirectSampling) view_enter_direct_sampling(app); + if(old == ViewBuildMessage) view_exit_build_message(app); + if(new == ViewBuildMessage) view_enter_build_message(app); + if(old == ViewInfo) view_exit_info(app); /* The frequency/modulation settings are actually a single view: * as long as the user stays between the two modes of this view we * don't need to call the exit-view callback. */ - if ((old == ViewFrequencySettings && new != ViewModulationSettings) || - (old == ViewModulationSettings && new != ViewFrequencySettings)) + if((old == ViewFrequencySettings && new != ViewModulationSettings) || + (old == ViewModulationSettings && new != ViewFrequencySettings)) view_exit_settings(app); ui_dismiss_alert(app); @@ -125,7 +135,7 @@ static void app_switch_view(ProtoViewApp *app, ProtoViewCurrentView switchto) { /* Allocate the application state and initialize a number of stuff. * This is called in the entry point to create the application state. */ ProtoViewApp* protoview_app_alloc() { - ProtoViewApp *app = malloc(sizeof(ProtoViewApp)); + ProtoViewApp* app = malloc(sizeof(ProtoViewApp)); // Init shared data structures RawSamples = raw_samples_alloc(); @@ -148,10 +158,10 @@ ProtoViewApp* protoview_app_alloc() { app->show_text_input = false; app->alert_dismiss_time = 0; app->current_view = ViewRawPulses; - for (int j = 0; j < ViewLast; j++) app->current_subview[j] = 0; + for(int j = 0; j < ViewLast; j++) app->current_subview[j] = 0; app->direct_sampling_enabled = false; app->view_privdata = malloc(PROTOVIEW_VIEW_PRIVDATA_LEN); - memset(app->view_privdata,0,PROTOVIEW_VIEW_PRIVDATA_LEN); + memset(app->view_privdata, 0, PROTOVIEW_VIEW_PRIVDATA_LEN); // Signal found and visualization defaults app->signal_bestlen = 0; @@ -176,17 +186,14 @@ ProtoViewApp* protoview_app_alloc() { app->txrx->environment = subghz_environment_alloc(); subghz_environment_set_protocol_registry( app->txrx->environment, (void*)&protoview_protocol_registry); - app->txrx->receiver = - subghz_receiver_alloc_init(app->txrx->environment); - subghz_receiver_set_filter(app->txrx->receiver, - SubGhzProtocolFlag_Decodable); + app->txrx->receiver = subghz_receiver_alloc_init(app->txrx->environment); + subghz_receiver_set_filter(app->txrx->receiver, SubGhzProtocolFlag_Decodable); subghz_worker_set_overrun_callback( - app->txrx->worker, - (SubGhzWorkerOverrunCallback)subghz_receiver_reset); + app->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); subghz_worker_set_pair_callback( app->txrx->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); subghz_worker_set_context(app->txrx->worker, app->txrx->receiver); - + app->frequency = subghz_setting_get_default_frequency(app->setting); app->modulation = 0; /* Defaults to ProtoViewModulations[0]. */ @@ -199,7 +206,7 @@ ProtoViewApp* protoview_app_alloc() { /* Free what the application allocated. It is not clear to me if the * Flipper OS, once the application exits, will be able to reclaim space * even if we forget to free something here. */ -void protoview_app_free(ProtoViewApp *app) { +void protoview_app_free(ProtoViewApp* app) { furi_assert(app); // Put CC1101 on sleep, this also restores charging. @@ -218,7 +225,7 @@ void protoview_app_free(ProtoViewApp *app) { subghz_setting_free(app->setting); // Worker stuff. - if (!app->txrx->debug_timer_sampling) { + if(!app->txrx->debug_timer_sampling) { subghz_receiver_free(app->txrx->receiver); subghz_environment_free(app->txrx->environment); subghz_worker_free(app->txrx->worker); @@ -236,8 +243,8 @@ void protoview_app_free(ProtoViewApp *app) { /* Called periodically. Do signal processing here. Data we process here * will be later displayed by the render callback. The side effect of this * function is to scan for signals and set DetectedSamples. */ -static void timer_callback(void *ctx) { - ProtoViewApp *app = ctx; +static void timer_callback(void* ctx) { + ProtoViewApp* app = ctx; uint32_t delta, lastidx = app->signal_last_scan_idx; /* scan_for_signal(), called by this function, deals with a @@ -245,14 +252,14 @@ static void timer_callback(void *ctx) { * cross-boundaries, it is enough if we scan each time the buffer fills * for 50% more compared to the last scan. Thanks to this check we * can avoid scanning too many times to just find the same data. */ - if (lastidx < RawSamples->idx) { + if(lastidx < RawSamples->idx) { delta = RawSamples->idx - lastidx; } else { delta = RawSamples->total - lastidx + RawSamples->idx; } - if (delta < RawSamples->total/2) return; + if(delta < RawSamples->total / 2) return; app->signal_last_scan_idx = RawSamples->idx; - scan_for_signal(app,RawSamples); + scan_for_signal(app, RawSamples); } /* This is the navigation callback we use in the view dispatcher used @@ -265,7 +272,7 @@ static void timer_callback(void *ctx) { * We just need a dummy callback returning false. We believe the * implementation should be changed and if no callback is set, it should be * the same as returning false. */ -static bool keyboard_view_dispatcher_navigation_callback(void *ctx) { +static bool keyboard_view_dispatcher_navigation_callback(void* ctx) { UNUSED(ctx); return false; } @@ -273,10 +280,10 @@ static bool keyboard_view_dispatcher_navigation_callback(void *ctx) { /* App entry point, as specified in application.fam. */ int32_t protoview_app_entry(void* p) { UNUSED(p); - ProtoViewApp *app = protoview_app_alloc(); + ProtoViewApp* app = protoview_app_alloc(); /* Create a timer. We do data analysis in the callback. */ - FuriTimer *timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, app); + FuriTimer* timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, app); furi_timer_start(timer, furi_kernel_get_tick_frequency() / 8); /* Start listening to signals immediately. */ @@ -291,71 +298,68 @@ int32_t protoview_app_entry(void* p) { InputEvent input; while(app->running) { FuriStatus qstat = furi_message_queue_get(app->event_queue, &input, 100); - if (qstat == FuriStatusOk) { - if (DEBUG_MSG) FURI_LOG_E(TAG, "Main Loop - Input: type %d key %u", - input.type, input.key); + if(qstat == FuriStatusOk) { + if(DEBUG_MSG) + FURI_LOG_E(TAG, "Main Loop - Input: type %d key %u", input.type, input.key); /* Handle navigation here. Then handle view-specific inputs * in the view specific handling function. */ - if (input.type == InputTypeShort && - input.key == InputKeyBack) - { - if (app->current_view != ViewRawPulses) { + if(input.type == InputTypeShort && input.key == InputKeyBack) { + if(app->current_view != ViewRawPulses) { /* If this is not the main app view, go there. */ - app_switch_view(app,ViewRawPulses); + app_switch_view(app, ViewRawPulses); } else { /* If we are in the main app view, warn the user * they needs to long press to really quit. */ - ui_show_alert(app,"Long press to exit",1000); + ui_show_alert(app, "Long press to exit", 1000); } - } else if (input.type == InputTypeLong && - input.key == InputKeyBack) - { + } else if(input.type == InputTypeLong && input.key == InputKeyBack) { app->running = 0; - } else if (input.type == InputTypeShort && - input.key == InputKeyRight && - ui_get_current_subview(app) == 0) - { + } else if( + input.type == InputTypeShort && input.key == InputKeyRight && + ui_get_current_subview(app) == 0) { /* Go to the next view. */ - app_switch_view(app,ViewGoNext); - } else if (input.type == InputTypeShort && - input.key == InputKeyLeft && - ui_get_current_subview(app) == 0) - { + app_switch_view(app, ViewGoNext); + } else if( + input.type == InputTypeShort && input.key == InputKeyLeft && + ui_get_current_subview(app) == 0) { /* Go to the previous view. */ - app_switch_view(app,ViewGoPrev); + app_switch_view(app, ViewGoPrev); } else { /* This is where we pass the control to the currently * active view input processing. */ switch(app->current_view) { case ViewRawPulses: - process_input_raw_pulses(app,input); + process_input_raw_pulses(app, input); break; case ViewInfo: - process_input_info(app,input); + process_input_info(app, input); break; case ViewFrequencySettings: case ViewModulationSettings: - process_input_settings(app,input); + process_input_settings(app, input); break; case ViewDirectSampling: - process_input_direct_sampling(app,input); + process_input_direct_sampling(app, input); break; case ViewBuildMessage: - process_input_build_message(app,input); + process_input_build_message(app, input); + break; + default: + furi_crash(TAG "Invalid view selected"); break; - default: furi_crash(TAG "Invalid view selected"); break; } } } else { /* Useful to understand if the app is still alive when it * does not respond because of bugs. */ - if (DEBUG_MSG) { - static int c = 0; c++; - if (!(c % 20)) FURI_LOG_E(TAG, "Loop timeout"); + if(DEBUG_MSG) { + static int c = 0; + c++; + if(!(c % 20)) FURI_LOG_E(TAG, "Loop timeout"); } } - if (app->show_text_input) { + if(app->show_text_input) { /* Remove our viewport: we need to use a view dispatcher * in order to show the standard Flipper keyboard. */ gui_remove_view_port(app->gui, app->view_port); @@ -368,11 +372,11 @@ int32_t protoview_app_entry(void* p) { * otherwise when the user presses back on the keyboard to * abort, the dispatcher will not stop. */ view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, - keyboard_view_dispatcher_navigation_callback); + app->view_dispatcher, keyboard_view_dispatcher_navigation_callback); app->text_input = text_input_alloc(); - view_dispatcher_set_event_callback_context(app->view_dispatcher,app); - view_dispatcher_add_view(app->view_dispatcher, 0, text_input_get_view(app->text_input)); + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + view_dispatcher_add_view( + app->view_dispatcher, 0, text_input_get_view(app->text_input)); view_dispatcher_switch_to_view(app->view_dispatcher, 0); /* Setup the text input view. The different parameters are set @@ -388,7 +392,8 @@ int32_t protoview_app_entry(void* p) { false); /* Run the dispatcher with the keyboard. */ - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + view_dispatcher_attach_to_gui( + app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); view_dispatcher_run(app->view_dispatcher); /* Undo all it: remove the view from the dispatcher, free it @@ -406,7 +411,7 @@ int32_t protoview_app_entry(void* p) { } /* App no longer running. Shut down and free. */ - if (app->txrx->txrx_state == TxRxStateRx) { + if(app->txrx->txrx_state == TxRxStateRx) { FURI_LOG_E(TAG, "Putting CC1101 to sleep before exiting."); radio_rx_end(app); radio_sleep(app); @@ -416,4 +421,3 @@ int32_t protoview_app_entry(void* p) { protoview_app_free(app); return 0; } - diff --git a/applications/plugins/protoview/app.h b/applications/plugins/protoview/app.h index 33bd85eb4..85007e345 100644 --- a/applications/plugins/protoview/app.h +++ b/applications/plugins/protoview/app.h @@ -66,11 +66,11 @@ typedef enum { /* ================================== RX/TX ================================= */ typedef struct { - const char *name; // Name to show to the user. - const char *id; // Identifier in the Flipper API/file. - FuriHalSubGhzPreset preset; // The preset ID. - uint8_t *custom; // If not null, a set of registers for - // the CC1101, specifying a custom preset. + const char* name; // Name to show to the user. + const char* id; // Identifier in the Flipper API/file. + FuriHalSubGhzPreset preset; // The preset ID. + uint8_t* custom; // If not null, a set of registers for + // the CC1101, specifying a custom preset. } ProtoViewModulation; extern ProtoViewModulation ProtoViewModulations[]; /* In app_subghz.c */ @@ -79,19 +79,19 @@ extern ProtoViewModulation ProtoViewModulations[]; /* In app_subghz.c */ * It receives data and we get our protocol "feed" callback called * with the level (1 or 0) and duration. */ struct ProtoViewTxRx { - bool freq_mod_changed; /* The user changed frequency and/or modulation + bool freq_mod_changed; /* The user changed frequency and/or modulation from the interface. There is to restart the radio with the right parameters. */ - SubGhzWorker* worker; /* Our background worker. */ + SubGhzWorker* worker; /* Our background worker. */ SubGhzEnvironment* environment; SubGhzReceiver* receiver; TxRxState txrx_state; /* Receiving, idle or sleeping? */ /* Timer sampling mode state. */ - bool debug_timer_sampling; /* Read data from GDO0 in a busy loop. Only + bool debug_timer_sampling; /* Read data from GDO0 in a busy loop. Only for testing. */ uint32_t last_g0_change_time; /* Last high->low (or reverse) switch. */ - bool last_g0_value; /* Current value (high or low): we are + bool last_g0_value; /* Current value (high or low): we are checking the duration in the timer handler. */ }; @@ -103,44 +103,44 @@ typedef struct ProtoViewTxRx ProtoViewTxRx; #define ALERT_MAX_LEN 32 struct ProtoViewApp { /* GUI */ - Gui *gui; - NotificationApp *notification; - ViewPort *view_port; /* We just use a raw viewport and we render + Gui* gui; + NotificationApp* notification; + ViewPort* view_port; /* We just use a raw viewport and we render everything into the low level canvas. */ - ProtoViewCurrentView current_view; /* Active left-right view ID. */ - int current_subview[ViewLast]; /* Active up-down subview ID. */ - FuriMessageQueue *event_queue; /* Keypress events go here. */ + ProtoViewCurrentView current_view; /* Active left-right view ID. */ + int current_subview[ViewLast]; /* Active up-down subview ID. */ + FuriMessageQueue* event_queue; /* Keypress events go here. */ /* Input text state. */ - ViewDispatcher *view_dispatcher; /* Used only when we want to show + ViewDispatcher* view_dispatcher; /* Used only when we want to show the text_input view for a moment. Otherwise it is set to null. */ - TextInput *text_input; + TextInput* text_input; bool show_text_input; - char *text_input_buffer; + char* text_input_buffer; uint32_t text_input_buffer_len; void (*text_input_done_callback)(void*); /* Alert state. */ - uint32_t alert_dismiss_time; /* Millisecond when the alert will be + uint32_t alert_dismiss_time; /* Millisecond when the alert will be no longer shown. Or zero if the alert is currently not set at all. */ char alert_text[ALERT_MAX_LEN]; /* Alert content. */ /* Radio related. */ - ProtoViewTxRx *txrx; /* Radio state. */ - SubGhzSetting *setting; /* A list of valid frequencies. */ + ProtoViewTxRx* txrx; /* Radio state. */ + SubGhzSetting* setting; /* A list of valid frequencies. */ /* Generic app state. */ - int running; /* Once false exists the app. */ + int running; /* Once false exists the app. */ uint32_t signal_bestlen; /* Longest coherent signal observed so far. */ uint32_t signal_last_scan_idx; /* Index of the buffer last time we performed the scan. */ - bool signal_decoded; /* Was the current signal decoded? */ - ProtoViewMsgInfo *msg_info; /* Decoded message info if not NULL. */ + bool signal_decoded; /* Was the current signal decoded? */ + ProtoViewMsgInfo* msg_info; /* Decoded message info if not NULL. */ bool direct_sampling_enabled; /* This special view needs an explicit acknowledge to work. */ - void *view_privdata; /* This is a piece of memory of total size + void* view_privdata; /* This is a piece of memory of total size PROTOVIEW_VIEW_PRIVDATA_LEN that it is initialized to zero when we switch to a a new view. While the view we are using @@ -149,12 +149,12 @@ struct ProtoViewApp { the pointer to a few specific-data structure. */ /* Raw view apps state. */ - uint32_t us_scale; /* microseconds per pixel. */ - uint32_t signal_offset; /* Long press left/right panning in raw view. */ + uint32_t us_scale; /* microseconds per pixel. */ + uint32_t signal_offset; /* Long press left/right panning in raw view. */ /* Configuration view app state. */ - uint32_t frequency; /* Current frequency. */ - uint8_t modulation; /* Current modulation ID, array index in the + uint32_t frequency; /* Current frequency. */ + uint8_t modulation; /* Current modulation ID, array index in the ProtoViewModulations table. */ }; @@ -165,18 +165,18 @@ struct ProtoViewApp { * in the message info view. */ #define PROTOVIEW_MSG_STR_LEN 32 typedef struct ProtoViewMsgInfo { - ProtoViewDecoder *decoder; /* The decoder that decoded the message. */ - ProtoViewFieldSet *fieldset; /* Decoded fields. */ + ProtoViewDecoder* decoder; /* The decoder that decoded the message. */ + ProtoViewFieldSet* fieldset; /* Decoded fields. */ /* Low level information of the detected signal: the following are filled * by the protocol decoding function: */ - uint32_t start_off; /* Pulses start offset in the bitmap. */ - uint32_t pulses_count; /* Number of pulses of the full message. */ + uint32_t start_off; /* Pulses start offset in the bitmap. */ + uint32_t pulses_count; /* Number of pulses of the full message. */ /* The following are passed already filled to the decoder. */ - uint32_t short_pulse_dur; /* Microseconds duration of the short pulse. */ + uint32_t short_pulse_dur; /* Microseconds duration of the short pulse. */ /* The following are filled by ProtoView core after the decoder returned * success. */ - uint8_t *bits; /* Bitmap with the signal. */ - uint32_t bits_bytes; /* Number of full bytes in the bitmap, that + uint8_t* bits; /* Bitmap with the signal. */ + uint32_t bits_bytes; /* Number of full bytes in the bitmap, that is 'pulses_count/8' rounded to the next integer. */ } ProtoViewMsgInfo; @@ -196,28 +196,28 @@ typedef enum { typedef struct { ProtoViewFieldType type; - uint32_t len; // Depends on type: - // Bits for integers (signed,unsigned,binary,hex). - // Number of characters for strings. - // Number of nibbles for bytes (1 for each 4 bits). - // Number of digits after dot for floats. - char *name; // Field name. + uint32_t len; // Depends on type: + // Bits for integers (signed,unsigned,binary,hex). + // Number of characters for strings. + // Number of nibbles for bytes (1 for each 4 bits). + // Number of digits after dot for floats. + char* name; // Field name. union { - char *str; // String type. - int64_t value; // Signed integer type. - uint64_t uvalue; // Unsigned integer type. - uint8_t *bytes; // Raw bytes type. - float fvalue; // Float type. + char* str; // String type. + int64_t value; // Signed integer type. + uint64_t uvalue; // Unsigned integer type. + uint8_t* bytes; // Raw bytes type. + float fvalue; // Float type. }; } ProtoViewField; typedef struct ProtoViewFieldSet { - ProtoViewField **fields; + ProtoViewField** fields; uint32_t numfields; } ProtoViewFieldSet; typedef struct ProtoViewDecoder { - const char *name; /* Protocol name. */ + const char* name; /* Protocol name. */ /* The decode function takes a buffer that is actually a bitmap, with * high and low levels represented as 0 and 1. The number of high/low * pulses represented by the bitmap is passed as the 'numbits' argument, @@ -225,15 +225,15 @@ typedef struct ProtoViewDecoder { * 'bits'. So 'numbytes' is mainly useful to pass as argument to other * functions that perform bit extraction with bound checking, such as * bitmap_get() and so forth. */ - bool (*decode)(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info); + bool (*decode)(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info); /* This method is used by the decoder to return the fields it needs * in order to build a new message. This way the message builder view * can ask the user to fill the right set of fields of the specified * type. */ - void (*get_fields)(ProtoViewFieldSet *fields); + void (*get_fields)(ProtoViewFieldSet* fields); /* This method takes the fields supported by the decoder, and * renders a message in 'samples'. */ - void (*build_message)(RawSamplesBuffer *samples, ProtoViewFieldSet *fields); + void (*build_message)(RawSamplesBuffer* samples, ProtoViewFieldSet* fields); } ProtoViewDecoder; extern RawSamplesBuffer *RawSamples, *DetectedSamples; @@ -244,76 +244,118 @@ uint32_t radio_rx(ProtoViewApp* app); void radio_idle(ProtoViewApp* app); void radio_rx_end(ProtoViewApp* app); void radio_sleep(ProtoViewApp* app); -void raw_sampling_worker_start(ProtoViewApp *app); -void raw_sampling_worker_stop(ProtoViewApp *app); -void radio_tx_signal(ProtoViewApp *app, FuriHalSubGhzAsyncTxCallback data_feeder, void *ctx); +void raw_sampling_worker_start(ProtoViewApp* app); +void raw_sampling_worker_stop(ProtoViewApp* app); +void radio_tx_signal(ProtoViewApp* app, FuriHalSubGhzAsyncTxCallback data_feeder, void* ctx); /* signal.c */ uint32_t duration_delta(uint32_t a, uint32_t b); -void reset_current_signal(ProtoViewApp *app); -void scan_for_signal(ProtoViewApp *app,RawSamplesBuffer *source); -bool bitmap_get(uint8_t *b, uint32_t blen, uint32_t bitpos); -void bitmap_set(uint8_t *b, uint32_t blen, uint32_t bitpos, bool val); -void bitmap_copy(uint8_t *d, uint32_t dlen, uint32_t doff, uint8_t *s, uint32_t slen, uint32_t soff, uint32_t count); -void bitmap_set_pattern(uint8_t *b, uint32_t blen, uint32_t off, const char *pat); -void bitmap_reverse_bytes_bits(uint8_t *p, uint32_t len); -bool bitmap_match_bits(uint8_t *b, uint32_t blen, uint32_t bitpos, const char *bits); -uint32_t bitmap_seek_bits(uint8_t *b, uint32_t blen, uint32_t startpos, uint32_t maxbits, const char *bits); -uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t offset, const char *zero_pattern, const char *one_pattern); -uint32_t convert_from_diff_manchester(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t off, bool previous); -void init_msg_info(ProtoViewMsgInfo *i, ProtoViewApp *app); -void free_msg_info(ProtoViewMsgInfo *i); +void reset_current_signal(ProtoViewApp* app); +void scan_for_signal(ProtoViewApp* app, RawSamplesBuffer* source); +bool bitmap_get(uint8_t* b, uint32_t blen, uint32_t bitpos); +void bitmap_set(uint8_t* b, uint32_t blen, uint32_t bitpos, bool val); +void bitmap_copy( + uint8_t* d, + uint32_t dlen, + uint32_t doff, + uint8_t* s, + uint32_t slen, + uint32_t soff, + uint32_t count); +void bitmap_set_pattern(uint8_t* b, uint32_t blen, uint32_t off, const char* pat); +void bitmap_reverse_bytes_bits(uint8_t* p, uint32_t len); +bool bitmap_match_bits(uint8_t* b, uint32_t blen, uint32_t bitpos, const char* bits); +uint32_t bitmap_seek_bits( + uint8_t* b, + uint32_t blen, + uint32_t startpos, + uint32_t maxbits, + const char* bits); +uint32_t convert_from_line_code( + uint8_t* buf, + uint64_t buflen, + uint8_t* bits, + uint32_t len, + uint32_t offset, + const char* zero_pattern, + const char* one_pattern); +uint32_t convert_from_diff_manchester( + uint8_t* buf, + uint64_t buflen, + uint8_t* bits, + uint32_t len, + uint32_t off, + bool previous); +void init_msg_info(ProtoViewMsgInfo* i, ProtoViewApp* app); +void free_msg_info(ProtoViewMsgInfo* i); /* signal_file.c */ -bool save_signal(ProtoViewApp *app, const char *filename); +bool save_signal(ProtoViewApp* app, const char* filename); /* view_*.c */ -void render_view_raw_pulses(Canvas *const canvas, ProtoViewApp *app); -void process_input_raw_pulses(ProtoViewApp *app, InputEvent input); -void render_view_settings(Canvas *const canvas, ProtoViewApp *app); -void process_input_settings(ProtoViewApp *app, InputEvent input); -void render_view_info(Canvas *const canvas, ProtoViewApp *app); -void process_input_info(ProtoViewApp *app, InputEvent input); -void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app); -void process_input_direct_sampling(ProtoViewApp *app, InputEvent input); -void render_view_build_message(Canvas *const canvas, ProtoViewApp *app); -void process_input_build_message(ProtoViewApp *app, InputEvent input); -void view_enter_build_message(ProtoViewApp *app); -void view_exit_build_message(ProtoViewApp *app); -void view_enter_direct_sampling(ProtoViewApp *app); -void view_exit_direct_sampling(ProtoViewApp *app); -void view_exit_settings(ProtoViewApp *app); -void view_exit_info(ProtoViewApp *app); -void adjust_raw_view_scale(ProtoViewApp *app, uint32_t short_pulse_dur); +void render_view_raw_pulses(Canvas* const canvas, ProtoViewApp* app); +void process_input_raw_pulses(ProtoViewApp* app, InputEvent input); +void render_view_settings(Canvas* const canvas, ProtoViewApp* app); +void process_input_settings(ProtoViewApp* app, InputEvent input); +void render_view_info(Canvas* const canvas, ProtoViewApp* app); +void process_input_info(ProtoViewApp* app, InputEvent input); +void render_view_direct_sampling(Canvas* const canvas, ProtoViewApp* app); +void process_input_direct_sampling(ProtoViewApp* app, InputEvent input); +void render_view_build_message(Canvas* const canvas, ProtoViewApp* app); +void process_input_build_message(ProtoViewApp* app, InputEvent input); +void view_enter_build_message(ProtoViewApp* app); +void view_exit_build_message(ProtoViewApp* app); +void view_enter_direct_sampling(ProtoViewApp* app); +void view_exit_direct_sampling(ProtoViewApp* app); +void view_exit_settings(ProtoViewApp* app); +void view_exit_info(ProtoViewApp* app); +void adjust_raw_view_scale(ProtoViewApp* app, uint32_t short_pulse_dur); /* ui.c */ -int ui_get_current_subview(ProtoViewApp *app); -void ui_show_available_subviews(Canvas *canvas, ProtoViewApp *app, int last_subview); -bool ui_process_subview_updown(ProtoViewApp *app, InputEvent input, int last_subview); -void ui_show_keyboard(ProtoViewApp *app, char *buffer, uint32_t buflen, - void (*done_callback)(void*)); -void ui_dismiss_keyboard(ProtoViewApp *app); -void ui_show_alert(ProtoViewApp *app, const char *text, uint32_t ttl); -void ui_dismiss_alert(ProtoViewApp *app); -void ui_draw_alert_if_needed(Canvas *canvas, ProtoViewApp *app); -void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const char* str, Color text_color, Color border_color); +int ui_get_current_subview(ProtoViewApp* app); +void ui_show_available_subviews(Canvas* canvas, ProtoViewApp* app, int last_subview); +bool ui_process_subview_updown(ProtoViewApp* app, InputEvent input, int last_subview); +void ui_show_keyboard( + ProtoViewApp* app, + char* buffer, + uint32_t buflen, + void (*done_callback)(void*)); +void ui_dismiss_keyboard(ProtoViewApp* app); +void ui_show_alert(ProtoViewApp* app, const char* text, uint32_t ttl); +void ui_dismiss_alert(ProtoViewApp* app); +void ui_draw_alert_if_needed(Canvas* canvas, ProtoViewApp* app); +void canvas_draw_str_with_border( + Canvas* canvas, + uint8_t x, + uint8_t y, + const char* str, + Color text_color, + Color border_color); /* fields.c */ -void fieldset_free(ProtoViewFieldSet *fs); -ProtoViewFieldSet *fieldset_new(void); -void fieldset_add_int(ProtoViewFieldSet *fs, const char *name, int64_t val, uint8_t bits); -void fieldset_add_uint(ProtoViewFieldSet *fs, const char *name, uint64_t uval, uint8_t bits); -void fieldset_add_hex(ProtoViewFieldSet *fs, const char *name, uint64_t uval, uint8_t bits); -void fieldset_add_bin(ProtoViewFieldSet *fs, const char *name, uint64_t uval, uint8_t bits); -void fieldset_add_str(ProtoViewFieldSet *fs, const char *name, const char *s); -void fieldset_add_bytes(ProtoViewFieldSet *fs, const char *name, const uint8_t *bytes, uint32_t count); -void fieldset_add_float(ProtoViewFieldSet *fs, const char *name, float val, uint32_t digits_after_dot); -const char *field_get_type_name(ProtoViewField *f); -int field_to_string(char *buf, size_t len, ProtoViewField *f); -bool field_set_from_string(ProtoViewField *f, char *buf, size_t len); -bool field_incr_value(ProtoViewField *f, int incr); -void fieldset_copy_matching_fields(ProtoViewFieldSet *dst, ProtoViewFieldSet *src); -void field_set_from_field(ProtoViewField *dst, ProtoViewField *src); +void fieldset_free(ProtoViewFieldSet* fs); +ProtoViewFieldSet* fieldset_new(void); +void fieldset_add_int(ProtoViewFieldSet* fs, const char* name, int64_t val, uint8_t bits); +void fieldset_add_uint(ProtoViewFieldSet* fs, const char* name, uint64_t uval, uint8_t bits); +void fieldset_add_hex(ProtoViewFieldSet* fs, const char* name, uint64_t uval, uint8_t bits); +void fieldset_add_bin(ProtoViewFieldSet* fs, const char* name, uint64_t uval, uint8_t bits); +void fieldset_add_str(ProtoViewFieldSet* fs, const char* name, const char* s); +void fieldset_add_bytes( + ProtoViewFieldSet* fs, + const char* name, + const uint8_t* bytes, + uint32_t count); +void fieldset_add_float( + ProtoViewFieldSet* fs, + const char* name, + float val, + uint32_t digits_after_dot); +const char* field_get_type_name(ProtoViewField* f); +int field_to_string(char* buf, size_t len, ProtoViewField* f); +bool field_set_from_string(ProtoViewField* f, char* buf, size_t len); +bool field_incr_value(ProtoViewField* f, int incr); +void fieldset_copy_matching_fields(ProtoViewFieldSet* dst, ProtoViewFieldSet* src); +void field_set_from_field(ProtoViewField* dst, ProtoViewField* src); /* crc.c */ -uint8_t crc8(const uint8_t *data, size_t len, uint8_t init, uint8_t poly); +uint8_t crc8(const uint8_t* data, size_t len, uint8_t init, uint8_t poly); diff --git a/applications/plugins/protoview/app_subghz.c b/applications/plugins/protoview/app_subghz.c index 55905e8a3..73e0e16ae 100644 --- a/applications/plugins/protoview/app_subghz.c +++ b/applications/plugins/protoview/app_subghz.c @@ -9,18 +9,20 @@ #include #include -void raw_sampling_worker_start(ProtoViewApp *app); -void raw_sampling_worker_stop(ProtoViewApp *app); +void raw_sampling_worker_start(ProtoViewApp* app); +void raw_sampling_worker_stop(ProtoViewApp* app); ProtoViewModulation ProtoViewModulations[] = { - {"OOK 650Khz", "FuriHalSubGhzPresetOok650Async", - FuriHalSubGhzPresetOok650Async, NULL}, - {"OOK 270Khz", "FuriHalSubGhzPresetOok270Async", - FuriHalSubGhzPresetOok270Async, NULL}, - {"2FSK 2.38Khz", "FuriHalSubGhzPreset2FSKDev238Async", - FuriHalSubGhzPreset2FSKDev238Async, NULL}, - {"2FSK 47.6Khz", "FuriHalSubGhzPreset2FSKDev476Async", - FuriHalSubGhzPreset2FSKDev476Async, NULL}, + {"OOK 650Khz", "FuriHalSubGhzPresetOok650Async", FuriHalSubGhzPresetOok650Async, NULL}, + {"OOK 270Khz", "FuriHalSubGhzPresetOok270Async", FuriHalSubGhzPresetOok270Async, NULL}, + {"2FSK 2.38Khz", + "FuriHalSubGhzPreset2FSKDev238Async", + FuriHalSubGhzPreset2FSKDev238Async, + NULL}, + {"2FSK 47.6Khz", + "FuriHalSubGhzPreset2FSKDev476Async", + FuriHalSubGhzPreset2FSKDev476Async, + NULL}, {"TPMS 1 (FSK)", NULL, 0, (uint8_t*)protoview_subghz_tpms1_fsk_async_regs}, {"TPMS 2 (OOK)", NULL, 0, (uint8_t*)protoview_subghz_tpms2_ook_async_regs}, {"TPMS 3 (FSK)", NULL, 0, (uint8_t*)protoview_subghz_tpms3_fsk_async_regs}, @@ -44,12 +46,10 @@ void radio_begin(ProtoViewApp* app) { /* The CC1101 preset can be either one of the standard presets, if * the modulation "custom" field is NULL, or a custom preset we * defined in custom_presets.h. */ - if (ProtoViewModulations[app->modulation].custom == NULL) { - furi_hal_subghz_load_preset( - ProtoViewModulations[app->modulation].preset); + if(ProtoViewModulations[app->modulation].custom == NULL) { + furi_hal_subghz_load_preset(ProtoViewModulations[app->modulation].preset); } else { - furi_hal_subghz_load_custom_preset( - ProtoViewModulations[app->modulation].custom); + furi_hal_subghz_load_custom_preset(ProtoViewModulations[app->modulation].custom); } furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); app->txrx->txrx_state = TxRxStateIDLE; @@ -61,10 +61,10 @@ void radio_begin(ProtoViewApp* app) { uint32_t radio_rx(ProtoViewApp* app) { furi_assert(app); if(!furi_hal_subghz_is_frequency_valid(app->frequency)) { - furi_crash(TAG" Incorrect RX frequency."); + furi_crash(TAG " Incorrect RX frequency."); } - if (app->txrx->txrx_state == TxRxStateRx) return app->frequency; + if(app->txrx->txrx_state == TxRxStateRx) return app->frequency; furi_hal_subghz_idle(); /* Put it into idle state in case it is sleeping. */ uint32_t value = furi_hal_subghz_set_frequency_and_path(app->frequency); @@ -72,10 +72,8 @@ uint32_t radio_rx(ProtoViewApp* app) { furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_flush_rx(); furi_hal_subghz_rx(); - if (!app->txrx->debug_timer_sampling) { - - furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, - app->txrx->worker); + if(!app->txrx->debug_timer_sampling) { + furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, app->txrx->worker); subghz_worker_start(app->txrx->worker); } else { raw_sampling_worker_start(app); @@ -88,8 +86,8 @@ uint32_t radio_rx(ProtoViewApp* app) { void radio_rx_end(ProtoViewApp* app) { furi_assert(app); - if (app->txrx->txrx_state == TxRxStateRx) { - if (!app->txrx->debug_timer_sampling) { + if(app->txrx->txrx_state == TxRxStateRx) { + if(!app->txrx->debug_timer_sampling) { if(subghz_worker_is_running(app->txrx->worker)) { subghz_worker_stop(app->txrx->worker); furi_hal_subghz_stop_async_rx(); @@ -105,7 +103,7 @@ void radio_rx_end(ProtoViewApp* app) { /* Put radio on sleep. */ void radio_sleep(ProtoViewApp* app) { furi_assert(app); - if (app->txrx->txrx_state == TxRxStateRx) { + if(app->txrx->txrx_state == TxRxStateRx) { /* We can't go from having an active RX worker to sleeping. * Stop the RX subsystems first. */ radio_rx_end(app); @@ -120,10 +118,10 @@ void radio_sleep(ProtoViewApp* app) { /* This function suspends the current RX state, switches to TX mode, * transmits the signal provided by the callback data_feeder, and later * restores the RX state if there was one. */ -void radio_tx_signal(ProtoViewApp *app, FuriHalSubGhzAsyncTxCallback data_feeder, void *ctx) { +void radio_tx_signal(ProtoViewApp* app, FuriHalSubGhzAsyncTxCallback data_feeder, void* ctx) { TxRxState oldstate = app->txrx->txrx_state; - if (oldstate == TxRxStateRx) radio_rx_end(app); + if(oldstate == TxRxStateRx) radio_rx_end(app); radio_begin(app); furi_hal_subghz_idle(); @@ -138,7 +136,7 @@ void radio_tx_signal(ProtoViewApp *app, FuriHalSubGhzAsyncTxCallback data_feeder furi_hal_subghz_idle(); radio_begin(app); - if (oldstate == TxRxStateRx) radio_rx(app); + if(oldstate == TxRxStateRx) radio_rx(app); } /* ============================= Raw sampling mode ============================= @@ -148,15 +146,15 @@ void radio_tx_signal(ProtoViewApp *app, FuriHalSubGhzAsyncTxCallback data_feeder * Flipper system. * ===========================================================================*/ -void protoview_timer_isr(void *ctx) { - ProtoViewApp *app = ctx; +void protoview_timer_isr(void* ctx) { + ProtoViewApp* app = ctx; bool level = furi_hal_gpio_read(&gpio_cc1101_g0); - if (app->txrx->last_g0_value != level) { + if(app->txrx->last_g0_value != level) { uint32_t now = DWT->CYCCNT; uint32_t dur = now - app->txrx->last_g0_change_time; dur /= furi_hal_cortex_instructions_per_microsecond(); - if (dur > 15000) dur = 15000; + if(dur > 15000) dur = 15000; raw_samples_add(RawSamples, app->txrx->last_g0_value, dur); app->txrx->last_g0_value = level; app->txrx->last_g0_change_time = now; @@ -164,13 +162,13 @@ void protoview_timer_isr(void *ctx) { LL_TIM_ClearFlag_UPDATE(TIM2); } -void raw_sampling_worker_start(ProtoViewApp *app) { +void raw_sampling_worker_start(ProtoViewApp* app) { UNUSED(app); LL_TIM_InitTypeDef tim_init = { - .Prescaler = 63, /* CPU frequency is ~64Mhz. */ + .Prescaler = 63, /* CPU frequency is ~64Mhz. */ .CounterMode = LL_TIM_COUNTERMODE_UP, - .Autoreload = 5, /* Sample every 5 us */ + .Autoreload = 5, /* Sample every 5 us */ }; LL_TIM_Init(TIM2, &tim_init); @@ -183,7 +181,7 @@ void raw_sampling_worker_start(ProtoViewApp *app) { FURI_LOG_E(TAG, "Timer enabled"); } -void raw_sampling_worker_stop(ProtoViewApp *app) { +void raw_sampling_worker_stop(ProtoViewApp* app) { UNUSED(app); FURI_CRITICAL_ENTER(); LL_TIM_DisableCounter(TIM2); diff --git a/applications/plugins/protoview/crc.c b/applications/plugins/protoview/crc.c index 38a809e10..94d482972 100644 --- a/applications/plugins/protoview/crc.c +++ b/applications/plugins/protoview/crc.c @@ -3,14 +3,13 @@ /* CRC8 with the specified initialization value 'init' and * polynomial 'poly'. */ -uint8_t crc8(const uint8_t *data, size_t len, uint8_t init, uint8_t poly) -{ +uint8_t crc8(const uint8_t* data, size_t len, uint8_t init, uint8_t poly) { uint8_t crc = init; size_t i, j; - for (i = 0; i < len; i++) { + for(i = 0; i < len; i++) { crc ^= data[i]; - for (j = 0; j < 8; j++) { - if ((crc & 0x80) != 0) + for(j = 0; j < 8; j++) { + if((crc & 0x80) != 0) crc = (uint8_t)((crc << 1) ^ poly); else crc <<= 1; diff --git a/applications/plugins/protoview/custom_presets.h b/applications/plugins/protoview/custom_presets.h index cb9a421c6..00aa49945 100644 --- a/applications/plugins/protoview/custom_presets.h +++ b/applications/plugins/protoview/custom_presets.h @@ -76,7 +76,8 @@ static uint8_t protoview_subghz_tpms1_fsk_async_regs[][2] = { // // Modem Configuration {CC1101_MDMCFG0, 0x00}, {CC1101_MDMCFG1, 0x02}, - {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized). Other code reading TPMS uses GFSK, but should be the same when in RX mode. + {CC1101_MDMCFG2, + 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized). Other code reading TPMS uses GFSK, but should be the same when in RX mode. {CC1101_MDMCFG3, 0x93}, // Data rate is 20kBaud {CC1101_MDMCFG4, 0x59}, // Rx bandwidth filter is 325 kHz {CC1101_DEVIATN, 0x41}, // Deviation 28.56 kHz @@ -106,8 +107,10 @@ static uint8_t protoview_subghz_tpms1_fsk_async_regs[][2] = { {0, 0}, /* CC1101 2FSK PATABLE. */ - {0xC0, 0}, {0,0}, {0,0}, {0,0} -}; + {0xC0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}; /* This is like the default Flipper OOK 640Khz bandwidth preset, but * the bandwidth is changed to 10kBaud to accomodate TPMS frequency. */ @@ -156,8 +159,10 @@ static const uint8_t protoview_subghz_tpms2_ook_async_regs[][2] = { {0, 0}, /* CC1101 OOK PATABLE. */ - {0, 0xC0}, {0,0}, {0,0}, {0,0} -}; + {0, 0xC0}, + {0, 0}, + {0, 0}, + {0, 0}}; /* 40 KBaud, 2FSK, 28 kHz deviation, 270 Khz bandwidth filter. */ static uint8_t protoview_subghz_tpms3_fsk_async_regs[][2] = { @@ -174,7 +179,8 @@ static uint8_t protoview_subghz_tpms3_fsk_async_regs[][2] = { // // Modem Configuration {CC1101_MDMCFG0, 0x00}, {CC1101_MDMCFG1, 0x02}, - {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized). Other code reading TPMS uses GFSK, but should be the same when in RX mode. + {CC1101_MDMCFG2, + 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized). Other code reading TPMS uses GFSK, but should be the same when in RX mode. {CC1101_MDMCFG3, 0x93}, // Data rate is 40kBaud {CC1101_MDMCFG4, 0x6A}, // 6 = BW filter 270kHz, A = Data rate exp {CC1101_DEVIATN, 0x41}, // Deviation 28kHz @@ -204,8 +210,10 @@ static uint8_t protoview_subghz_tpms3_fsk_async_regs[][2] = { {0, 0}, /* CC1101 2FSK PATABLE. */ - {0xC0, 0}, {0,0}, {0,0}, {0,0} -}; + {0xC0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}; /* FSK 19k dev, 325 Khz filter, 20kBaud. Works well with Toyota. */ static uint8_t protoview_subghz_tpms4_fsk_async_regs[][2] = { @@ -250,6 +258,7 @@ static uint8_t protoview_subghz_tpms4_fsk_async_regs[][2] = { {0, 0}, /* CC1101 2FSK PATABLE. */ - {0xC0, 0}, {0,0}, {0,0}, {0,0} -}; - + {0xC0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}; diff --git a/applications/plugins/protoview/data_feed.c b/applications/plugins/protoview/data_feed.c index a3bed238e..81d1a8020 100644 --- a/applications/plugins/protoview/data_feed.c +++ b/applications/plugins/protoview/data_feed.c @@ -14,7 +14,7 @@ const SubGhzProtocol subghz_protocol_protoview; /* The feed() method puts data in the RawSamples global (protected by * a mutex). */ -extern RawSamplesBuffer *RawSamples; +extern RawSamplesBuffer* RawSamples; /* This is totally dummy: we just define the decoder base for the async * system to work but we don't really use it if not to collect raw @@ -26,8 +26,7 @@ typedef struct SubGhzProtocolDecoderprotoview { void* subghz_protocol_decoder_protoview_alloc(SubGhzEnvironment* environment) { UNUSED(environment); - SubGhzProtocolDecoderprotoview* instance = - malloc(sizeof(SubGhzProtocolDecoderprotoview)); + SubGhzProtocolDecoderprotoview* instance = malloc(sizeof(SubGhzProtocolDecoderprotoview)); instance->base.protocol = &subghz_protocol_protoview; return instance; } @@ -66,8 +65,7 @@ uint8_t subghz_protocol_decoder_protoview_get_hash_data(void* context) { bool subghz_protocol_decoder_protoview_serialize( void* context, FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) -{ + SubGhzRadioPreset* preset) { UNUSED(context); UNUSED(flipper_format); UNUSED(preset); @@ -75,15 +73,13 @@ bool subghz_protocol_decoder_protoview_serialize( } /* Not used. */ -bool subghz_protocol_decoder_protoview_deserialize(void* context, FlipperFormat* flipper_format) -{ +bool subghz_protocol_decoder_protoview_deserialize(void* context, FlipperFormat* flipper_format) { UNUSED(context); UNUSED(flipper_format); return false; } -void subhz_protocol_decoder_protoview_get_string(void* context, FuriString* output) -{ +void subhz_protocol_decoder_protoview_get_string(void* context, FuriString* output) { furi_assert(context); furi_string_cat_printf(output, "Protoview"); } @@ -116,5 +112,4 @@ const SubGhzProtocol* protoview_protocol_registry_items[] = { const SubGhzProtocolRegistry protoview_protocol_registry = { .items = protoview_protocol_registry_items, - .size = COUNT_OF(protoview_protocol_registry_items) -}; + .size = COUNT_OF(protoview_protocol_registry_items)}; diff --git a/applications/plugins/protoview/fields.c b/applications/plugins/protoview/fields.c index bc62cda54..47d573f4f 100644 --- a/applications/plugins/protoview/fields.c +++ b/applications/plugins/protoview/fields.c @@ -7,8 +7,8 @@ /* Create a new field of the specified type. Without populating its * type-specific value. */ -static ProtoViewField *field_new(ProtoViewFieldType type, const char *name) { - ProtoViewField *f = malloc(sizeof(*f)); +static ProtoViewField* field_new(ProtoViewFieldType type, const char* name) { + ProtoViewField* f = malloc(sizeof(*f)); f->type = type; f->name = strdup(name); return f; @@ -16,72 +16,80 @@ static ProtoViewField *field_new(ProtoViewFieldType type, const char *name) { /* Free only the auxiliary data of a field, used to represent the * current type. Name and type are not touched. */ -static void field_free_aux_data(ProtoViewField *f) { +static void field_free_aux_data(ProtoViewField* f) { switch(f->type) { - case FieldTypeStr: free(f->str); break; - case FieldTypeBytes: free(f->bytes); break; - default: break; // Nothing to free for other types. + case FieldTypeStr: + free(f->str); + break; + case FieldTypeBytes: + free(f->bytes); + break; + default: + break; // Nothing to free for other types. } } /* Free a field an associated data. */ -static void field_free(ProtoViewField *f) { +static void field_free(ProtoViewField* f) { field_free_aux_data(f); free(f->name); free(f); } /* Return the type of the field as string. */ -const char *field_get_type_name(ProtoViewField *f) { +const char* field_get_type_name(ProtoViewField* f) { switch(f->type) { - case FieldTypeStr: return "str"; - case FieldTypeSignedInt: return "int"; - case FieldTypeUnsignedInt: return "uint"; - case FieldTypeBinary: return "bin"; - case FieldTypeHex: return "hex"; - case FieldTypeBytes: return "bytes"; - case FieldTypeFloat: return "float"; + case FieldTypeStr: + return "str"; + case FieldTypeSignedInt: + return "int"; + case FieldTypeUnsignedInt: + return "uint"; + case FieldTypeBinary: + return "bin"; + case FieldTypeHex: + return "hex"; + case FieldTypeBytes: + return "bytes"; + case FieldTypeFloat: + return "float"; } return "unknown"; } /* Set a string representation of the specified field in buf. */ -int field_to_string(char *buf, size_t len, ProtoViewField *f) { +int field_to_string(char* buf, size_t len, ProtoViewField* f) { switch(f->type) { case FieldTypeStr: - return snprintf(buf,len,"%s", f->str); + return snprintf(buf, len, "%s", f->str); case FieldTypeSignedInt: - return snprintf(buf,len,"%lld", (long long) f->value); + return snprintf(buf, len, "%lld", (long long)f->value); case FieldTypeUnsignedInt: - return snprintf(buf,len,"%llu", (unsigned long long) f->uvalue); - case FieldTypeBinary: - { - uint64_t test_bit = (1 << (f->len-1)); - uint64_t idx = 0; - while(idx < len-1 && test_bit) { - buf[idx++] = (f->uvalue & test_bit) ? '1' : '0'; - test_bit >>= 1; - } - buf[idx] = 0; - return idx; + return snprintf(buf, len, "%llu", (unsigned long long)f->uvalue); + case FieldTypeBinary: { + uint64_t test_bit = (1 << (f->len - 1)); + uint64_t idx = 0; + while(idx < len - 1 && test_bit) { + buf[idx++] = (f->uvalue & test_bit) ? '1' : '0'; + test_bit >>= 1; } + buf[idx] = 0; + return idx; + } case FieldTypeHex: - return snprintf(buf, len, "%*llX", (int)(f->len+7)/8, f->uvalue); + return snprintf(buf, len, "%*llX", (int)(f->len + 7) / 8, f->uvalue); case FieldTypeFloat: return snprintf(buf, len, "%.*f", (int)f->len, (double)f->fvalue); - case FieldTypeBytes: - { - uint64_t idx = 0; - while(idx < len-1 && idx < f->len) { - const char *charset = "0123456789ABCDEF"; - uint32_t nibble = idx & 1 ? - (f->bytes[idx/2] & 0xf) : - (f->bytes[idx/2] >> 4); - buf[idx++] = charset[nibble]; - } - buf[idx] = 0; - return idx; + case FieldTypeBytes: { + uint64_t idx = 0; + while(idx < len - 1 && idx < f->len) { + const char* charset = "0123456789ABCDEF"; + uint32_t nibble = idx & 1 ? (f->bytes[idx / 2] & 0xf) : (f->bytes[idx / 2] >> 4); + buf[idx++] = charset[nibble]; } + buf[idx] = 0; + return idx; + } } return 0; } @@ -96,7 +104,7 @@ int field_to_string(char *buf, size_t len, ProtoViewField *f) { * The function returns true if the filed was successfully set to the * new value, otherwise if the specified value is invalid for the * field type, false is returned. */ -bool field_set_from_string(ProtoViewField *f, char *buf, size_t len) { +bool field_set_from_string(ProtoViewField* f, char* buf, size_t len) { // Initialize values to zero since the Flipper sscanf() implementation // is fuzzy... may populate only part of the value. long long val = 0; @@ -107,80 +115,78 @@ bool field_set_from_string(ProtoViewField *f, char *buf, size_t len) { case FieldTypeStr: free(f->str); f->len = len; - f->str = malloc(len+1); - memcpy(f->str,buf,len+1); + f->str = malloc(len + 1); + memcpy(f->str, buf, len + 1); break; case FieldTypeSignedInt: - if (!sscanf(buf,"%lld",&val)) return false; + if(!sscanf(buf, "%lld", &val)) return false; f->value = val; break; case FieldTypeUnsignedInt: - if (!sscanf(buf,"%llu",&uval)) return false; + if(!sscanf(buf, "%llu", &uval)) return false; f->uvalue = uval; break; - case FieldTypeBinary: - { - uint64_t bit_to_set = (1 << (len-1)); - uint64_t idx = 0; - uval = 0; - while(buf[idx]) { - if (buf[idx] == '1') uval |= bit_to_set; - else if (buf[idx] != '0') return false; - bit_to_set >>= 1; - idx++; - } - f->uvalue = uval; + case FieldTypeBinary: { + uint64_t bit_to_set = (1 << (len - 1)); + uint64_t idx = 0; + uval = 0; + while(buf[idx]) { + if(buf[idx] == '1') + uval |= bit_to_set; + else if(buf[idx] != '0') + return false; + bit_to_set >>= 1; + idx++; } - break; + f->uvalue = uval; + } break; case FieldTypeHex: - if (!sscanf(buf,"%llx",&uval) && - !sscanf(buf,"%llX",&uval)) return false; + if(!sscanf(buf, "%llx", &uval) && !sscanf(buf, "%llX", &uval)) return false; f->uvalue = uval; break; case FieldTypeFloat: - if (!sscanf(buf,"%f",&fval)) return false; + if(!sscanf(buf, "%f", &fval)) return false; f->fvalue = fval; break; - case FieldTypeBytes: - { - if (len > f->len) return false; - uint64_t idx = 0; - while(buf[idx]) { - uint8_t nibble = 0; - char c = toupper(buf[idx]); - if (c >= '0' && c <= '9') nibble = c-'0'; - else if (c >= 'A' && c <= 'F') nibble = 10+(c-'A'); - else return false; + case FieldTypeBytes: { + if(len > f->len) return false; + uint64_t idx = 0; + while(buf[idx]) { + uint8_t nibble = 0; + char c = toupper(buf[idx]); + if(c >= '0' && c <= '9') + nibble = c - '0'; + else if(c >= 'A' && c <= 'F') + nibble = 10 + (c - 'A'); + else + return false; - if (idx & 1) { - f->bytes[idx/2] = - (f->bytes[idx/2] & 0xF0) | nibble; - } else { - f->bytes[idx/2] = - (f->bytes[idx/2] & 0x0F) | (nibble<<4); - } - idx++; + if(idx & 1) { + f->bytes[idx / 2] = (f->bytes[idx / 2] & 0xF0) | nibble; + } else { + f->bytes[idx / 2] = (f->bytes[idx / 2] & 0x0F) | (nibble << 4); } - buf[idx] = 0; + idx++; } - break; + buf[idx] = 0; + } break; } return true; } /* Set the 'dst' field to contain a copy of the value of the 'src' * field. The field name is not modified. */ -void field_set_from_field(ProtoViewField *dst, ProtoViewField *src) { +void field_set_from_field(ProtoViewField* dst, ProtoViewField* src) { field_free_aux_data(dst); dst->type = src->type; dst->len = src->len; - switch(src->type) { + switch(src->type) { case FieldTypeStr: dst->str = strdup(src->str); break; case FieldTypeBytes: dst->bytes = malloc(src->len); - memcpy(dst->bytes,src->bytes,dst->len); + memcpy(dst->bytes, src->bytes, dst->len); break; case FieldTypeSignedInt: dst->value = src->value; @@ -199,159 +205,159 @@ void field_set_from_field(ProtoViewField *dst, ProtoViewField *src) { /* Increment the specified field value of 'incr'. If the field type * does not support increments false is returned, otherwise the * action is performed. */ -bool field_incr_value(ProtoViewField *f, int incr) { +bool field_incr_value(ProtoViewField* f, int incr) { switch(f->type) { - case FieldTypeStr: return false; - case FieldTypeSignedInt: { - /* Wrap around depending on the number of bits (f->len) + case FieldTypeStr: + return false; + case FieldTypeSignedInt: { + /* Wrap around depending on the number of bits (f->len) * the integer was declared to have. */ - int64_t max = (1ULL << (f->len-1))-1; - int64_t min = -max-1; - int64_t v = (int64_t)f->value + incr; - if (v > max) v = min+(v-max-1); - if (v < min) v = max+(v-min+1); - f->value = v; - break; - } - case FieldTypeBinary: - case FieldTypeHex: - case FieldTypeUnsignedInt: { - /* Wrap around like for the unsigned case, but here + int64_t max = (1ULL << (f->len - 1)) - 1; + int64_t min = -max - 1; + int64_t v = (int64_t)f->value + incr; + if(v > max) v = min + (v - max - 1); + if(v < min) v = max + (v - min + 1); + f->value = v; + break; + } + case FieldTypeBinary: + case FieldTypeHex: + case FieldTypeUnsignedInt: { + /* Wrap around like for the unsigned case, but here * is simpler. */ - uint64_t max = (1ULL << f->len)-1; // Broken for 64 bits. - uint64_t uv = (uint64_t)f->value + incr; - if (uv > max) uv = uv & max; - f->uvalue = uv; - break; - } - case FieldTypeFloat: - f->fvalue += incr; - break; - case FieldTypeBytes: { - // For bytes we only support single unit increments. - if (incr != -1 && incr != 1) return false; - for (int j = f->len-1; j >= 0; j--) { - uint8_t nibble = (j&1) ? (f->bytes[j/2] & 0x0F) : - ((f->bytes[j/2] & 0xF0) >> 4); + uint64_t max = (1ULL << f->len) - 1; // Broken for 64 bits. + uint64_t uv = (uint64_t)f->value + incr; + if(uv > max) uv = uv & max; + f->uvalue = uv; + break; + } + case FieldTypeFloat: + f->fvalue += incr; + break; + case FieldTypeBytes: { + // For bytes we only support single unit increments. + if(incr != -1 && incr != 1) return false; + for(int j = f->len - 1; j >= 0; j--) { + uint8_t nibble = (j & 1) ? (f->bytes[j / 2] & 0x0F) : ((f->bytes[j / 2] & 0xF0) >> 4); - nibble += incr; - nibble &= 0x0F; + nibble += incr; + nibble &= 0x0F; - f->bytes[j/2] = (j&1) ? ((f->bytes[j/2] & 0xF0) | nibble) : - ((f->bytes[j/2] & 0x0F) | (nibble<<4)); + f->bytes[j / 2] = (j & 1) ? ((f->bytes[j / 2] & 0xF0) | nibble) : + ((f->bytes[j / 2] & 0x0F) | (nibble << 4)); - /* Propagate the operation on overflow of this nibble. */ - if ((incr == 1 && nibble == 0) || - (incr == -1 && nibble == 0xf)) - { - continue; - } - break; // Otherwise stop the loop here. + /* Propagate the operation on overflow of this nibble. */ + if((incr == 1 && nibble == 0) || (incr == -1 && nibble == 0xf)) { + continue; } - break; + break; // Otherwise stop the loop here. } + break; + } } return true; } - /* Free a field set and its contained fields. */ -void fieldset_free(ProtoViewFieldSet *fs) { - for (uint32_t j = 0; j < fs->numfields; j++) - field_free(fs->fields[j]); +void fieldset_free(ProtoViewFieldSet* fs) { + for(uint32_t j = 0; j < fs->numfields; j++) field_free(fs->fields[j]); free(fs->fields); free(fs); } /* Allocate and init an empty field set. */ -ProtoViewFieldSet *fieldset_new(void) { - ProtoViewFieldSet *fs = malloc(sizeof(*fs)); +ProtoViewFieldSet* fieldset_new(void) { + ProtoViewFieldSet* fs = malloc(sizeof(*fs)); fs->numfields = 0; fs->fields = NULL; return fs; } /* Append an already allocated field at the end of the specified field set. */ -static void fieldset_add_field(ProtoViewFieldSet *fs, ProtoViewField *field) { +static void fieldset_add_field(ProtoViewFieldSet* fs, ProtoViewField* field) { fs->numfields++; - fs->fields = realloc(fs->fields,sizeof(ProtoViewField*)*fs->numfields); - fs->fields[fs->numfields-1] = field; + fs->fields = realloc(fs->fields, sizeof(ProtoViewField*) * fs->numfields); + fs->fields[fs->numfields - 1] = field; } /* Allocate and append an integer field. */ -void fieldset_add_int(ProtoViewFieldSet *fs, const char *name, int64_t val, uint8_t bits) { - ProtoViewField *f = field_new(FieldTypeSignedInt,name); +void fieldset_add_int(ProtoViewFieldSet* fs, const char* name, int64_t val, uint8_t bits) { + ProtoViewField* f = field_new(FieldTypeSignedInt, name); f->value = val; f->len = bits; - fieldset_add_field(fs,f); + fieldset_add_field(fs, f); } /* Allocate and append an unsigned field. */ -void fieldset_add_uint(ProtoViewFieldSet *fs, const char *name, uint64_t uval, uint8_t bits) { - ProtoViewField *f = field_new(FieldTypeUnsignedInt,name); +void fieldset_add_uint(ProtoViewFieldSet* fs, const char* name, uint64_t uval, uint8_t bits) { + ProtoViewField* f = field_new(FieldTypeUnsignedInt, name); f->uvalue = uval; f->len = bits; - fieldset_add_field(fs,f); + fieldset_add_field(fs, f); } /* Allocate and append a hex field. This is an unsigned number but * with an hex representation. */ -void fieldset_add_hex(ProtoViewFieldSet *fs, const char *name, uint64_t uval, uint8_t bits) { - ProtoViewField *f = field_new(FieldTypeHex,name); +void fieldset_add_hex(ProtoViewFieldSet* fs, const char* name, uint64_t uval, uint8_t bits) { + ProtoViewField* f = field_new(FieldTypeHex, name); f->uvalue = uval; f->len = bits; - fieldset_add_field(fs,f); + fieldset_add_field(fs, f); } /* Allocate and append a bin field. This is an unsigned number but * with a binary representation. */ -void fieldset_add_bin(ProtoViewFieldSet *fs, const char *name, uint64_t uval, uint8_t bits) { - ProtoViewField *f = field_new(FieldTypeBinary,name); +void fieldset_add_bin(ProtoViewFieldSet* fs, const char* name, uint64_t uval, uint8_t bits) { + ProtoViewField* f = field_new(FieldTypeBinary, name); f->uvalue = uval; f->len = bits; - fieldset_add_field(fs,f); + fieldset_add_field(fs, f); } /* Allocate and append a string field. */ -void fieldset_add_str(ProtoViewFieldSet *fs, const char *name, const char *s) { - ProtoViewField *f = field_new(FieldTypeStr,name); +void fieldset_add_str(ProtoViewFieldSet* fs, const char* name, const char* s) { + ProtoViewField* f = field_new(FieldTypeStr, name); f->str = strdup(s); f->len = strlen(s); - fieldset_add_field(fs,f); + fieldset_add_field(fs, f); } /* Allocate and append a bytes field. Note that 'count' is specified in * nibbles (bytes*2). */ -void fieldset_add_bytes(ProtoViewFieldSet *fs, const char *name, const uint8_t *bytes, uint32_t count_nibbles) { - uint32_t numbytes = (count_nibbles+count_nibbles%2)/2; - ProtoViewField *f = field_new(FieldTypeBytes,name); +void fieldset_add_bytes( + ProtoViewFieldSet* fs, + const char* name, + const uint8_t* bytes, + uint32_t count_nibbles) { + uint32_t numbytes = (count_nibbles + count_nibbles % 2) / 2; + ProtoViewField* f = field_new(FieldTypeBytes, name); f->bytes = malloc(numbytes); - memcpy(f->bytes,bytes,numbytes); + memcpy(f->bytes, bytes, numbytes); f->len = count_nibbles; - fieldset_add_field(fs,f); + fieldset_add_field(fs, f); } /* Allocate and append a float field. */ -void fieldset_add_float(ProtoViewFieldSet *fs, const char *name, float val, uint32_t digits_after_dot) { - ProtoViewField *f = field_new(FieldTypeFloat,name); +void fieldset_add_float( + ProtoViewFieldSet* fs, + const char* name, + float val, + uint32_t digits_after_dot) { + ProtoViewField* f = field_new(FieldTypeFloat, name); f->fvalue = val; f->len = digits_after_dot; - fieldset_add_field(fs,f); + fieldset_add_field(fs, f); } /* For each field of the destination filedset 'dst', look for a matching * field name/type in the source fieldset 'src', and if one is found copy * its value into the 'dst' field. */ -void fieldset_copy_matching_fields(ProtoViewFieldSet *dst, - ProtoViewFieldSet *src) -{ - for (uint32_t j = 0; j < dst->numfields; j++) { - for (uint32_t i = 0; i < src->numfields; i++) { - if (dst->fields[j]->type == src->fields[i]->type && - !strcmp(dst->fields[j]->name,src->fields[i]->name)) - { - field_set_from_field(dst->fields[j], - src->fields[i]); +void fieldset_copy_matching_fields(ProtoViewFieldSet* dst, ProtoViewFieldSet* src) { + for(uint32_t j = 0; j < dst->numfields; j++) { + for(uint32_t i = 0; i < src->numfields; i++) { + if(dst->fields[j]->type == src->fields[i]->type && + !strcmp(dst->fields[j]->name, src->fields[i]->name)) { + field_set_from_field(dst->fields[j], src->fields[i]); } } } diff --git a/applications/plugins/protoview/protocols/b4b1.c b/applications/plugins/protoview/protocols/b4b1.c index 7308d1211..52c59d24b 100644 --- a/applications/plugins/protoview/protocols/b4b1.c +++ b/applications/plugins/protoview/protocols/b4b1.c @@ -9,9 +9,9 @@ #include "../app.h" -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { - if (numbits < 30) return false; - const char *sync_patterns[3] = { +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { + if(numbits < 30) return false; + const char* sync_patterns[3] = { "10000000000000000000000000000001", /* 30 zero bits. */ "100000000000000000000000000000001", /* 31 zero bits. */ "1000000000000000000000000000000001", /* 32 zero bits. */ @@ -19,70 +19,67 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView uint32_t off; int j; - for (j = 0; j < 3; j++) { - off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_patterns[j]); - if (off != BITMAP_SEEK_NOT_FOUND) break; + for(j = 0; j < 3; j++) { + off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_patterns[j]); + if(off != BITMAP_SEEK_NOT_FOUND) break; } - if (off == BITMAP_SEEK_NOT_FOUND) return false; - if (DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 preamble at: %lu",off); + if(off == BITMAP_SEEK_NOT_FOUND) return false; + if(DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 preamble at: %lu", off); info->start_off = off; // Seek data setction. Why -1? Last bit is data. - off += strlen(sync_patterns[j])-1; + off += strlen(sync_patterns[j]) - 1; uint8_t d[3]; /* 24 bits of data. */ - uint32_t decoded = - convert_from_line_code(d,sizeof(d),bits,numbytes,off,"1000","1110"); + uint32_t decoded = convert_from_line_code(d, sizeof(d), bits, numbytes, off, "1000", "1110"); - if (DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 decoded: %lu",decoded); - if (decoded < 24) return false; + if(DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 decoded: %lu", decoded); + if(decoded < 24) return false; - off += 24*4; // seek to end symbol offset to calculate the length. + off += 24 * 4; // seek to end symbol offset to calculate the length. off++; // In this protocol there is a final pulse as terminator. info->pulses_count = off - info->start_off; - fieldset_add_bytes(info->fieldset,"id",d,5); - fieldset_add_uint(info->fieldset,"button",d[2]&0xf,4); + fieldset_add_bytes(info->fieldset, "id", d, 5); + fieldset_add_uint(info->fieldset, "button", d[2] & 0xf, 4); return true; } /* Give fields and defaults for the signal creator. */ -static void get_fields(ProtoViewFieldSet *fieldset) { - uint8_t default_id[3]= {0xAB, 0xCD, 0xE0}; - fieldset_add_bytes(fieldset,"id",default_id,5); - fieldset_add_uint(fieldset,"button",1,4); +static void get_fields(ProtoViewFieldSet* fieldset) { + uint8_t default_id[3] = {0xAB, 0xCD, 0xE0}; + fieldset_add_bytes(fieldset, "id", default_id, 5); + fieldset_add_uint(fieldset, "button", 1, 4); } /* Create a signal. */ -static void build_message(RawSamplesBuffer *samples, ProtoViewFieldSet *fs) -{ +static void build_message(RawSamplesBuffer* samples, ProtoViewFieldSet* fs) { uint32_t te = 334; // Short pulse duration in microseconds. // Sync: 1 te pulse, 31 te gap. - raw_samples_add(samples,true,te); - raw_samples_add(samples,false,te*31); + raw_samples_add(samples, true, te); + raw_samples_add(samples, false, te * 31); // ID + button state uint8_t data[3]; - memcpy(data,fs->fields[0]->bytes,3); - data[2] = (data[2]&0xF0) | (fs->fields[1]->uvalue & 0xF); - for (uint32_t j = 0; j < 24; j++) { - if (bitmap_get(data,sizeof(data),j)) { - raw_samples_add(samples,true,te*3); - raw_samples_add(samples,false,te); + memcpy(data, fs->fields[0]->bytes, 3); + data[2] = (data[2] & 0xF0) | (fs->fields[1]->uvalue & 0xF); + for(uint32_t j = 0; j < 24; j++) { + if(bitmap_get(data, sizeof(data), j)) { + raw_samples_add(samples, true, te * 3); + raw_samples_add(samples, false, te); } else { - raw_samples_add(samples,true,te); - raw_samples_add(samples,false,te*3); + raw_samples_add(samples, true, te); + raw_samples_add(samples, false, te * 3); } } // Signal terminator. Just a single short pulse. - raw_samples_add(samples,true,te); + raw_samples_add(samples, true, te); } ProtoViewDecoder B4B1Decoder = { .name = "PT/SC remote", .decode = decode, .get_fields = get_fields, - .build_message = build_message -}; + .build_message = build_message}; diff --git a/applications/plugins/protoview/protocols/keeloq.c b/applications/plugins/protoview/protocols/keeloq.c index 0741eac47..298c690d4 100644 --- a/applications/plugins/protoview/protocols/keeloq.c +++ b/applications/plugins/protoview/protocols/keeloq.c @@ -24,16 +24,16 @@ #include "../app.h" -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { - +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { /* In the sync pattern, we require the 12 high/low pulses and at least * half the gap we expect (5 pulses times, one is the final zero in the * 24 symbols high/low sequence, then other 4). */ - const char *sync_pattern = "101010101010101010101010" "0000"; - uint8_t sync_len = 24+4; - if (numbits-sync_len+sync_len < 3*66) return false; - uint32_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); - if (off == BITMAP_SEEK_NOT_FOUND) return false; + const char* sync_pattern = "101010101010101010101010" + "0000"; + uint8_t sync_len = 24 + 4; + if(numbits - sync_len + sync_len < 3 * 66) return false; + uint32_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); + if(off == BITMAP_SEEK_NOT_FOUND) return false; info->start_off = off; off += sync_len; // Seek start of message. @@ -42,84 +42,77 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView * symbols of gap, to avoid missing the signal for a matter of wrong * timing. */ uint8_t gap_len = 0; - while(gap_len <= 7 && bitmap_get(bits,numbytes,off+gap_len) == 0) - gap_len++; - if (gap_len < 3 || gap_len > 7) return false; + while(gap_len <= 7 && bitmap_get(bits, numbytes, off + gap_len) == 0) gap_len++; + if(gap_len < 3 || gap_len > 7) return false; off += gap_len; FURI_LOG_E(TAG, "Keeloq preamble+sync found"); uint8_t raw[9] = {0}; - uint32_t decoded = - convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, - "110","100"); /* Pulse width modulation. */ + uint32_t decoded = convert_from_line_code( + raw, sizeof(raw), bits, numbytes, off, "110", "100"); /* Pulse width modulation. */ FURI_LOG_E(TAG, "Keeloq decoded bits: %lu", decoded); - if (decoded < 66) return false; /* Require the full 66 bits. */ + if(decoded < 66) return false; /* Require the full 66 bits. */ - info->pulses_count = (off+66*3) - info->start_off; + info->pulses_count = (off + 66 * 3) - info->start_off; - bitmap_reverse_bytes_bits(raw,sizeof(raw)); /* Keeloq is LSB first. */ + bitmap_reverse_bytes_bits(raw, sizeof(raw)); /* Keeloq is LSB first. */ - int buttons = raw[7]>>4; - int lowbat = (raw[8]&0x1) == 0; // Actual bit meaning: good battery level - int alwaysone = (raw[8]&0x2) != 0; + int buttons = raw[7] >> 4; + int lowbat = (raw[8] & 0x1) == 0; // Actual bit meaning: good battery level + int alwaysone = (raw[8] & 0x2) != 0; - fieldset_add_bytes(info->fieldset,"encr",raw,8); - raw[7] = raw[7]<<4; // Make ID bits contiguous - fieldset_add_bytes(info->fieldset,"id",raw+4,7); // 28 bits, 7 nibbles - fieldset_add_bin(info->fieldset,"s[2,1,0,3]",buttons,4); - fieldset_add_bin(info->fieldset,"low battery",lowbat,1); - fieldset_add_bin(info->fieldset,"always one",alwaysone,1); + fieldset_add_bytes(info->fieldset, "encr", raw, 8); + raw[7] = raw[7] << 4; // Make ID bits contiguous + fieldset_add_bytes(info->fieldset, "id", raw + 4, 7); // 28 bits, 7 nibbles + fieldset_add_bin(info->fieldset, "s[2,1,0,3]", buttons, 4); + fieldset_add_bin(info->fieldset, "low battery", lowbat, 1); + fieldset_add_bin(info->fieldset, "always one", alwaysone, 1); return true; } -static void get_fields(ProtoViewFieldSet *fieldset) { +static void get_fields(ProtoViewFieldSet* fieldset) { uint8_t remote_id[4] = {0xab, 0xcd, 0xef, 0xa0}; uint8_t encr[4] = {0xab, 0xab, 0xab, 0xab}; - fieldset_add_bytes(fieldset,"encr",encr,8); - fieldset_add_bytes(fieldset,"id",remote_id,7); - fieldset_add_bin(fieldset,"s[2,1,0,3]",2,4); - fieldset_add_bin(fieldset,"low battery",0,1); - fieldset_add_bin(fieldset,"always one",1,1); + fieldset_add_bytes(fieldset, "encr", encr, 8); + fieldset_add_bytes(fieldset, "id", remote_id, 7); + fieldset_add_bin(fieldset, "s[2,1,0,3]", 2, 4); + fieldset_add_bin(fieldset, "low battery", 0, 1); + fieldset_add_bin(fieldset, "always one", 1, 1); } -static void build_message(RawSamplesBuffer *samples, ProtoViewFieldSet *fieldset) -{ +static void build_message(RawSamplesBuffer* samples, ProtoViewFieldSet* fieldset) { uint32_t te = 380; // Short pulse duration in microseconds. // Sync: 12 pairs of pulse/gap + 9 times gap - for (int j = 0; j < 12; j++) { - raw_samples_add(samples,true,te); - raw_samples_add(samples,false,te); + for(int j = 0; j < 12; j++) { + raw_samples_add(samples, true, te); + raw_samples_add(samples, false, te); } - raw_samples_add(samples,false,te*9); + raw_samples_add(samples, false, te * 9); // Data, 66 bits. uint8_t data[9] = {0}; - memcpy(data,fieldset->fields[0]->bytes,4); // Encrypted part. - memcpy(data+4,fieldset->fields[1]->bytes,4); // ID. - data[7] = data[7]>>4 | fieldset->fields[2]->uvalue << 4; // s[2,1,0,3] + memcpy(data, fieldset->fields[0]->bytes, 4); // Encrypted part. + memcpy(data + 4, fieldset->fields[1]->bytes, 4); // ID. + data[7] = data[7] >> 4 | fieldset->fields[2]->uvalue << 4; // s[2,1,0,3] int low_battery = fieldset->fields[3] != 0; int always_one = fieldset->fields[4] != 0; low_battery = !low_battery; // Bit real meaning is good battery level. data[8] |= low_battery; data[8] |= (always_one << 1); - bitmap_reverse_bytes_bits(data,sizeof(data)); /* Keeloq is LSB first. */ + bitmap_reverse_bytes_bits(data, sizeof(data)); /* Keeloq is LSB first. */ - for (int j = 0; j < 66; j++) { - if (bitmap_get(data,9,j)) { - raw_samples_add(samples,true,te); - raw_samples_add(samples,false,te*2); + for(int j = 0; j < 66; j++) { + if(bitmap_get(data, 9, j)) { + raw_samples_add(samples, true, te); + raw_samples_add(samples, false, te * 2); } else { - raw_samples_add(samples,true,te*2); - raw_samples_add(samples,false,te); + raw_samples_add(samples, true, te * 2); + raw_samples_add(samples, false, te); } } } -ProtoViewDecoder KeeloqDecoder = { - .name = "Keeloq", - .decode = decode, - .get_fields = get_fields, - .build_message = build_message -}; +ProtoViewDecoder KeeloqDecoder = + {.name = "Keeloq", .decode = decode, .get_fields = get_fields, .build_message = build_message}; diff --git a/applications/plugins/protoview/protocols/oregon2.c b/applications/plugins/protoview/protocols/oregon2.c index 1d909a504..f67e85a2d 100644 --- a/applications/plugins/protoview/protocols/oregon2.c +++ b/applications/plugins/protoview/protocols/oregon2.c @@ -6,11 +6,14 @@ #include "../app.h" -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { - if (numbits < 32) return false; - const char *sync_pattern = "01100110" "01100110" "10010110" "10010110"; - uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); - if (off == BITMAP_SEEK_NOT_FOUND) return false; +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { + if(numbits < 32) return false; + const char* sync_pattern = "01100110" + "01100110" + "10010110" + "10010110"; + uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); + if(off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Oregon2 preamble+sync found"); info->start_off = off; @@ -18,50 +21,61 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView uint8_t buffer[8], raw[8] = {0}; uint32_t decoded = - convert_from_line_code(buffer,sizeof(buffer),bits,numbytes,off,"1001","0110"); + convert_from_line_code(buffer, sizeof(buffer), bits, numbytes, off, "1001", "0110"); FURI_LOG_E(TAG, "Oregon2 decoded bits: %lu", decoded); - if (decoded < 11*4) return false; /* Minimum len to extract some data. */ - info->pulses_count = (off+11*4*4) - info->start_off; + if(decoded < 11 * 4) return false; /* Minimum len to extract some data. */ + info->pulses_count = (off + 11 * 4 * 4) - info->start_off; char temp[3] = {0}, hum[2] = {0}; uint8_t deviceid[2]; - for (int j = 0; j < 64; j += 4) { + for(int j = 0; j < 64; j += 4) { uint8_t nib[1]; - nib[0] = (bitmap_get(buffer,8,j+0) | - bitmap_get(buffer,8,j+1) << 1 | - bitmap_get(buffer,8,j+2) << 2 | - bitmap_get(buffer,8,j+3) << 3); - if (DEBUG_MSG) FURI_LOG_E(TAG, "Not inverted nibble[%d]: %x", j/4, (unsigned int)nib[0]); - raw[j/8] |= nib[0] << (4-(j%4)); - switch(j/4) { - case 1: deviceid[0] |= nib[0]; break; - case 0: deviceid[0] |= nib[0] << 4; break; - case 3: deviceid[1] |= nib[0]; break; - case 2: deviceid[1] |= nib[0] << 4; break; - case 10: temp[0] = nib[0]; break; + nib[0] = + (bitmap_get(buffer, 8, j + 0) | bitmap_get(buffer, 8, j + 1) << 1 | + bitmap_get(buffer, 8, j + 2) << 2 | bitmap_get(buffer, 8, j + 3) << 3); + if(DEBUG_MSG) FURI_LOG_E(TAG, "Not inverted nibble[%d]: %x", j / 4, (unsigned int)nib[0]); + raw[j / 8] |= nib[0] << (4 - (j % 4)); + switch(j / 4) { + case 1: + deviceid[0] |= nib[0]; + break; + case 0: + deviceid[0] |= nib[0] << 4; + break; + case 3: + deviceid[1] |= nib[0]; + break; + case 2: + deviceid[1] |= nib[0] << 4; + break; + case 10: + temp[0] = nib[0]; + break; /* Fixme: take the temperature sign from nibble 11. */ - case 9: temp[1] = nib[0]; break; - case 8: temp[2] = nib[0]; break; - case 13: hum[0] = nib[0]; break; - case 12: hum[1] = nib[0]; break; + case 9: + temp[1] = nib[0]; + break; + case 8: + temp[2] = nib[0]; + break; + case 13: + hum[0] = nib[0]; + break; + case 12: + hum[1] = nib[0]; + break; } } - float tempval = ((temp[0]-'0')*10) + - (temp[1]-'0') + - ((float)(temp[2]-'0')*0.1); - int humval = (hum[0]-'0')*10 + (hum[1]-'0'); + float tempval = ((temp[0] - '0') * 10) + (temp[1] - '0') + ((float)(temp[2] - '0') * 0.1); + int humval = (hum[0] - '0') * 10 + (hum[1] - '0'); - fieldset_add_bytes(info->fieldset,"Sensor ID",deviceid,4); - fieldset_add_float(info->fieldset,"Temperature",tempval,1); - fieldset_add_uint(info->fieldset,"Humidity",humval,7); + fieldset_add_bytes(info->fieldset, "Sensor ID", deviceid, 4); + fieldset_add_float(info->fieldset, "Temperature", tempval, 1); + fieldset_add_uint(info->fieldset, "Humidity", humval, 7); return true; } -ProtoViewDecoder Oregon2Decoder = { - .name = "Oregon2", - .decode = decode, - .get_fields = NULL, - .build_message = NULL -}; +ProtoViewDecoder Oregon2Decoder = + {.name = "Oregon2", .decode = decode, .get_fields = NULL, .build_message = NULL}; diff --git a/applications/plugins/protoview/protocols/tpms/citroen.c b/applications/plugins/protoview/protocols/tpms/citroen.c index d8a1681e4..ecd8fb983 100644 --- a/applications/plugins/protoview/protocols/tpms/citroen.c +++ b/applications/plugins/protoview/protocols/tpms/citroen.c @@ -7,55 +7,49 @@ #include "../../app.h" -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { - +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { /* We consider a preamble of 17 symbols. They are more, but the decoding * is more likely to happen if we don't pretend to receive from the * very start of the message. */ uint32_t sync_len = 17; - const char *sync_pattern = "10101010101010110"; - if (numbits-sync_len < 8*10) return false; /* Expect 10 bytes. */ + const char* sync_pattern = "10101010101010110"; + if(numbits - sync_len < 8 * 10) return false; /* Expect 10 bytes. */ - uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); - if (off == BITMAP_SEEK_NOT_FOUND) return false; + uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); + if(off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Renault TPMS preamble+sync found"); info->start_off = off; off += sync_len; /* Skip preamble + sync. */ uint8_t raw[10]; - uint32_t decoded = - convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, - "01","10"); /* Manchester. */ + uint32_t decoded = convert_from_line_code( + raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester. */ FURI_LOG_E(TAG, "Citroen TPMS decoded bits: %lu", decoded); - if (decoded < 8*10) return false; /* Require the full 10 bytes. */ + if(decoded < 8 * 10) return false; /* Require the full 10 bytes. */ /* Check the CRC. It's a simple XOR of bytes 1-9, the first byte * is not included. The meaning of the first byte is unknown and * we don't display it. */ uint8_t crc = 0; - for (int j = 1; j < 10; j++) crc ^= raw[j]; - if (crc != 0) return false; /* Require sane checksum. */ + for(int j = 1; j < 10; j++) crc ^= raw[j]; + if(crc != 0) return false; /* Require sane checksum. */ - info->pulses_count = (off+8*10*2) - info->start_off; + info->pulses_count = (off + 8 * 10 * 2) - info->start_off; int repeat = raw[5] & 0xf; - float kpa = (float)raw[6]*1.364; - int temp = raw[7]-50; + float kpa = (float)raw[6] * 1.364; + int temp = raw[7] - 50; int battery = raw[8]; /* This may be the battery. It's not clear. */ - fieldset_add_bytes(info->fieldset,"Tire ID",raw+1,4*2); - fieldset_add_float(info->fieldset,"Pressure kpa",kpa,2); - fieldset_add_int(info->fieldset,"Temperature C",temp,8); - fieldset_add_uint(info->fieldset,"Repeat",repeat,4); - fieldset_add_uint(info->fieldset,"Battery",battery,8); + fieldset_add_bytes(info->fieldset, "Tire ID", raw + 1, 4 * 2); + fieldset_add_float(info->fieldset, "Pressure kpa", kpa, 2); + fieldset_add_int(info->fieldset, "Temperature C", temp, 8); + fieldset_add_uint(info->fieldset, "Repeat", repeat, 4); + fieldset_add_uint(info->fieldset, "Battery", battery, 8); return true; } -ProtoViewDecoder CitroenTPMSDecoder = { - .name = "Citroen TPMS", - .decode = decode, - .get_fields = NULL, - .build_message = NULL -}; +ProtoViewDecoder CitroenTPMSDecoder = + {.name = "Citroen TPMS", .decode = decode, .get_fields = NULL, .build_message = NULL}; diff --git a/applications/plugins/protoview/protocols/tpms/ford.c b/applications/plugins/protoview/protocols/tpms/ford.c index abdb692ee..3816e72f9 100644 --- a/applications/plugins/protoview/protocols/tpms/ford.c +++ b/applications/plugins/protoview/protocols/tpms/ford.c @@ -10,54 +10,49 @@ #include "../../app.h" -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { + const char* sync_pattern = "010101010101" + "0110"; + uint8_t sync_len = 12 + 4; /* We just use 12 preamble symbols + sync. */ + if(numbits - sync_len < 8 * 8) return false; - const char *sync_pattern = "010101010101" "0110"; - uint8_t sync_len = 12+4; /* We just use 12 preamble symbols + sync. */ - if (numbits-sync_len < 8*8) return false; - - uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); - if (off == BITMAP_SEEK_NOT_FOUND) return false; + uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); + if(off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Fort TPMS preamble+sync found"); info->start_off = off; off += sync_len; /* Skip preamble and sync. */ uint8_t raw[8]; - uint32_t decoded = - convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, - "01","10"); /* Manchester. */ + uint32_t decoded = convert_from_line_code( + raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester. */ FURI_LOG_E(TAG, "Ford TPMS decoded bits: %lu", decoded); - if (decoded < 8*8) return false; /* Require the full 8 bytes. */ + if(decoded < 8 * 8) return false; /* Require the full 8 bytes. */ /* CRC is just the sum of the first 7 bytes MOD 256. */ uint8_t crc = 0; - for (int j = 0; j < 7; j++) crc += raw[j]; - if (crc != raw[7]) return false; /* Require sane CRC. */ + for(int j = 0; j < 7; j++) crc += raw[j]; + if(crc != raw[7]) return false; /* Require sane CRC. */ - info->pulses_count = (off+8*8*2) - info->start_off; + info->pulses_count = (off + 8 * 8 * 2) - info->start_off; - float psi = 0.25 * (((raw[6]&0x20)<<3)|raw[4]); + float psi = 0.25 * (((raw[6] & 0x20) << 3) | raw[4]); /* Temperature apperas to be valid only if the most significant * bit of the value is not set. Otherwise its meaning is unknown. * Likely useful to alternatively send temperature or other info. */ - int temp = raw[5] & 0x80 ? 0 : raw[5]-56; + int temp = raw[5] & 0x80 ? 0 : raw[5] - 56; int flags = raw[5] & 0x7f; int car_moving = (raw[6] & 0x44) == 0x44; - fieldset_add_bytes(info->fieldset,"Tire ID",raw,4*2); - fieldset_add_float(info->fieldset,"Pressure psi",psi,2); - fieldset_add_int(info->fieldset,"Temperature C",temp,8); - fieldset_add_hex(info->fieldset,"Flags",flags,7); - fieldset_add_uint(info->fieldset,"Moving",car_moving,1); + fieldset_add_bytes(info->fieldset, "Tire ID", raw, 4 * 2); + fieldset_add_float(info->fieldset, "Pressure psi", psi, 2); + fieldset_add_int(info->fieldset, "Temperature C", temp, 8); + fieldset_add_hex(info->fieldset, "Flags", flags, 7); + fieldset_add_uint(info->fieldset, "Moving", car_moving, 1); return true; } -ProtoViewDecoder FordTPMSDecoder = { - .name = "Ford TPMS", - .decode = decode, - .get_fields = NULL, - .build_message = NULL -}; +ProtoViewDecoder FordTPMSDecoder = + {.name = "Ford TPMS", .decode = decode, .get_fields = NULL, .build_message = NULL}; diff --git a/applications/plugins/protoview/protocols/tpms/renault.c b/applications/plugins/protoview/protocols/tpms/renault.c index 09de77d17..3d8fc43d5 100644 --- a/applications/plugins/protoview/protocols/tpms/renault.c +++ b/applications/plugins/protoview/protocols/tpms/renault.c @@ -6,85 +6,82 @@ #include "../../app.h" #define USE_TEST_VECTOR 0 -static const char *test_vector = +static const char* test_vector = "...01010101010101010110" // Preamble + sync /* The following is Marshal encoded, so each two characters are * actaully one bit. 01 = 0, 10 = 1. */ "010110010110" // Flags. "10011001101010011001" // Pressure, multiply by 0.75 to obtain kpa. - // 244 kpa here. - "1010010110011010" // Temperature, subtract 30 to obtain celsius. 22C here. + // 244 kpa here. + "1010010110011010" // Temperature, subtract 30 to obtain celsius. 22C here. "1001010101101001" "0101100110010101" - "1001010101100110" // Tire ID. 0x7AD779 here. + "1001010101100110" // Tire ID. 0x7AD779 here. "0101010101010101" - "0101010101010101" // Two FF bytes (usually). Unknown. + "0101010101010101" // Two FF bytes (usually). Unknown. "0110010101010101"; // CRC8 with (poly 7, initialization 0). -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { - - if (USE_TEST_VECTOR) { /* Test vector to check that decoding works. */ - bitmap_set_pattern(bits,numbytes,0,test_vector); +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { + if(USE_TEST_VECTOR) { /* Test vector to check that decoding works. */ + bitmap_set_pattern(bits, numbytes, 0, test_vector); numbits = strlen(test_vector); } - if (numbits-12 < 9*8) return false; + if(numbits - 12 < 9 * 8) return false; - const char *sync_pattern = "01010101010101010110"; - uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); - if (off == BITMAP_SEEK_NOT_FOUND) return false; + const char* sync_pattern = "01010101010101010110"; + uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); + if(off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Renault TPMS preamble+sync found"); info->start_off = off; off += 20; /* Skip preamble. */ uint8_t raw[9]; - uint32_t decoded = - convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, - "01","10"); /* Manchester. */ + uint32_t decoded = convert_from_line_code( + raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester. */ FURI_LOG_E(TAG, "Renault TPMS decoded bits: %lu", decoded); - if (decoded < 8*9) return false; /* Require the full 9 bytes. */ - if (crc8(raw,8,0,7) != raw[8]) return false; /* Require sane CRC. */ + if(decoded < 8 * 9) return false; /* Require the full 9 bytes. */ + if(crc8(raw, 8, 0, 7) != raw[8]) return false; /* Require sane CRC. */ - info->pulses_count = (off+8*9*2) - info->start_off; + info->pulses_count = (off + 8 * 9 * 2) - info->start_off; - uint8_t flags = raw[0]>>2; - float kpa = 0.75 * ((uint32_t)((raw[0]&3)<<8) | raw[1]); - int temp = raw[2]-30; + uint8_t flags = raw[0] >> 2; + float kpa = 0.75 * ((uint32_t)((raw[0] & 3) << 8) | raw[1]); + int temp = raw[2] - 30; - fieldset_add_bytes(info->fieldset,"Tire ID",raw+3,3*2); - fieldset_add_float(info->fieldset,"Pressure kpa",kpa,2); - fieldset_add_int(info->fieldset,"Temperature C",temp,8); - fieldset_add_hex(info->fieldset,"Flags",flags,6); - fieldset_add_bytes(info->fieldset,"Unknown1",raw+6,2); - fieldset_add_bytes(info->fieldset,"Unknown2",raw+7,2); + fieldset_add_bytes(info->fieldset, "Tire ID", raw + 3, 3 * 2); + fieldset_add_float(info->fieldset, "Pressure kpa", kpa, 2); + fieldset_add_int(info->fieldset, "Temperature C", temp, 8); + fieldset_add_hex(info->fieldset, "Flags", flags, 6); + fieldset_add_bytes(info->fieldset, "Unknown1", raw + 6, 2); + fieldset_add_bytes(info->fieldset, "Unknown2", raw + 7, 2); return true; } /* Give fields and defaults for the signal creator. */ -static void get_fields(ProtoViewFieldSet *fieldset) { - uint8_t default_id[3]= {0xAB, 0xCD, 0xEF}; - fieldset_add_bytes(fieldset,"Tire ID",default_id,3*2); - fieldset_add_float(fieldset,"Pressure kpa",123,2); - fieldset_add_int(fieldset,"Temperature C",20,8); +static void get_fields(ProtoViewFieldSet* fieldset) { + uint8_t default_id[3] = {0xAB, 0xCD, 0xEF}; + fieldset_add_bytes(fieldset, "Tire ID", default_id, 3 * 2); + fieldset_add_float(fieldset, "Pressure kpa", 123, 2); + fieldset_add_int(fieldset, "Temperature C", 20, 8); // We don't know what flags are, but 1B is a common value. - fieldset_add_hex(fieldset,"Flags",0x1b,6); - fieldset_add_bytes(fieldset,"Unknown1",(uint8_t*)"\xff",2); - fieldset_add_bytes(fieldset,"Unknown2",(uint8_t*)"\xff",2); + fieldset_add_hex(fieldset, "Flags", 0x1b, 6); + fieldset_add_bytes(fieldset, "Unknown1", (uint8_t*)"\xff", 2); + fieldset_add_bytes(fieldset, "Unknown2", (uint8_t*)"\xff", 2); } /* Create a Renault TPMS signal, according to the fields provided. */ -static void build_message(RawSamplesBuffer *samples, ProtoViewFieldSet *fieldset) -{ +static void build_message(RawSamplesBuffer* samples, ProtoViewFieldSet* fieldset) { uint32_t te = 50; // Short pulse duration in microseconds. // Preamble + sync - const char *psync = "01010101010101010101010101010110"; - const char *p = psync; + const char* psync = "01010101010101010101010101010110"; + const char* p = psync; while(*p) { - raw_samples_add_or_update(samples,*p == '1',te); + raw_samples_add_or_update(samples, *p == '1', te); p++; } @@ -93,21 +90,21 @@ static void build_message(RawSamplesBuffer *samples, ProtoViewFieldSet *fieldset unsigned int raw_pressure = fieldset->fields[1]->fvalue * 4 / 3; data[0] = fieldset->fields[3]->uvalue << 2; // Flags data[0] |= (raw_pressure >> 8) & 3; // Pressure kpa high 2 bits - data[1] = raw_pressure & 0xff; // Pressure kpa low 8 bits + data[1] = raw_pressure & 0xff; // Pressure kpa low 8 bits data[2] = fieldset->fields[2]->value + 30; // Temperature C - memcpy(data+3,fieldset->fields[0]->bytes,6); // ID, 24 bits. - data[6] = fieldset->fields[4]->bytes[0]; // Unknown 1 - data[7] = fieldset->fields[5]->bytes[0]; // Unknown 2 - data[8] = crc8(data,8,0,7); + memcpy(data + 3, fieldset->fields[0]->bytes, 6); // ID, 24 bits. + data[6] = fieldset->fields[4]->bytes[0]; // Unknown 1 + data[7] = fieldset->fields[5]->bytes[0]; // Unknown 2 + data[8] = crc8(data, 8, 0, 7); // Generate Manchester code for each bit - for (uint32_t j = 0; j < 9*8; j++) { - if (bitmap_get(data,sizeof(data),j)) { - raw_samples_add_or_update(samples,true,te); - raw_samples_add_or_update(samples,false,te); + for(uint32_t j = 0; j < 9 * 8; j++) { + if(bitmap_get(data, sizeof(data), j)) { + raw_samples_add_or_update(samples, true, te); + raw_samples_add_or_update(samples, false, te); } else { - raw_samples_add_or_update(samples,false,te); - raw_samples_add_or_update(samples,true,te); + raw_samples_add_or_update(samples, false, te); + raw_samples_add_or_update(samples, true, te); } } } @@ -116,5 +113,4 @@ ProtoViewDecoder RenaultTPMSDecoder = { .name = "Renault TPMS", .decode = decode, .get_fields = get_fields, - .build_message = build_message -}; + .build_message = build_message}; diff --git a/applications/plugins/protoview/protocols/tpms/schrader.c b/applications/plugins/protoview/protocols/tpms/schrader.c index ae25e39bb..7dc85a2cb 100644 --- a/applications/plugins/protoview/protocols/tpms/schrader.c +++ b/applications/plugins/protoview/protocols/tpms/schrader.c @@ -11,20 +11,21 @@ #include "../../app.h" #define USE_TEST_VECTOR 0 -static const char *test_vector = "000000111101010101011010010110010110101001010110100110011001100101010101011010100110100110011010101010101010101010101010101010101010101010101010"; +static const char* test_vector = + "000000111101010101011010010110010110101001010110100110011001100101010101011010100110100110011010101010101010101010101010101010101010101010101010"; -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { - - if (USE_TEST_VECTOR) { /* Test vector to check that decoding works. */ - bitmap_set_pattern(bits,numbytes,0,test_vector); +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { + if(USE_TEST_VECTOR) { /* Test vector to check that decoding works. */ + bitmap_set_pattern(bits, numbytes, 0, test_vector); numbits = strlen(test_vector); } - if (numbits < 64) return false; /* Preamble + data. */ + if(numbits < 64) return false; /* Preamble + data. */ - const char *sync_pattern = "1111010101" "01011010"; - uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); - if (off == BITMAP_SEEK_NOT_FOUND) return false; + const char* sync_pattern = "1111010101" + "01011010"; + uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); + if(off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Schrader TPMS gap+preamble found"); info->start_off = off; @@ -34,38 +35,33 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView uint8_t raw[8]; uint8_t id[4]; - uint32_t decoded = - convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, - "01","10"); /* Manchester code. */ + uint32_t decoded = convert_from_line_code( + raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester code. */ FURI_LOG_E(TAG, "Schrader TPMS decoded bits: %lu", decoded); - if (decoded < 64) return false; /* Require the full 8 bytes. */ + if(decoded < 64) return false; /* Require the full 8 bytes. */ raw[0] |= 0xf0; // Fix the preamble nibble for checksum computation. - uint8_t cksum = crc8(raw,sizeof(raw)-1,0xf0,0x7); - if (cksum != raw[7]) { + uint8_t cksum = crc8(raw, sizeof(raw) - 1, 0xf0, 0x7); + if(cksum != raw[7]) { FURI_LOG_E(TAG, "Schrader TPMS checksum mismatch"); return false; } - info->pulses_count = (off+8*8*2) - info->start_off; + info->pulses_count = (off + 8 * 8 * 2) - info->start_off; - float kpa = (float)raw[5]*2.5; - int temp = raw[6]-50; - id[0] = raw[1]&7; + float kpa = (float)raw[5] * 2.5; + int temp = raw[6] - 50; + id[0] = raw[1] & 7; id[1] = raw[2]; id[2] = raw[3]; id[3] = raw[4]; - fieldset_add_bytes(info->fieldset,"Tire ID",id,4*2); - fieldset_add_float(info->fieldset,"Pressure kpa",kpa,2); - fieldset_add_int(info->fieldset,"Temperature C",temp,8); + fieldset_add_bytes(info->fieldset, "Tire ID", id, 4 * 2); + fieldset_add_float(info->fieldset, "Pressure kpa", kpa, 2); + fieldset_add_int(info->fieldset, "Temperature C", temp, 8); return true; } -ProtoViewDecoder SchraderTPMSDecoder = { - .name = "Schrader TPMS", - .decode = decode, - .get_fields = NULL, - .build_message = NULL -}; +ProtoViewDecoder SchraderTPMSDecoder = + {.name = "Schrader TPMS", .decode = decode, .get_fields = NULL, .build_message = NULL}; diff --git a/applications/plugins/protoview/protocols/tpms/schrader_eg53ma4.c b/applications/plugins/protoview/protocols/tpms/schrader_eg53ma4.c index 0105010bd..45accf1a1 100644 --- a/applications/plugins/protoview/protocols/tpms/schrader_eg53ma4.c +++ b/applications/plugins/protoview/protocols/tpms/schrader_eg53ma4.c @@ -15,50 +15,45 @@ #include "../../app.h" -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { + const char* sync_pattern = "010101010101" + "01100101"; + uint8_t sync_len = 12 + 8; /* We just use 12 preamble symbols + sync. */ + if(numbits - sync_len + 8 < 8 * 10) return false; - const char *sync_pattern = "010101010101" "01100101"; - uint8_t sync_len = 12+8; /* We just use 12 preamble symbols + sync. */ - if (numbits-sync_len+8 < 8*10) return false; - - uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); - if (off == BITMAP_SEEK_NOT_FOUND) return false; + uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); + if(off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Schrader EG53MA4 TPMS preamble+sync found"); info->start_off = off; - off += sync_len-8; /* Skip preamble, not sync that is part of the data. */ + off += sync_len - 8; /* Skip preamble, not sync that is part of the data. */ uint8_t raw[10]; - uint32_t decoded = - convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, - "01","10"); /* Manchester code. */ + uint32_t decoded = convert_from_line_code( + raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester code. */ FURI_LOG_E(TAG, "Schrader EG53MA4 TPMS decoded bits: %lu", decoded); - if (decoded < 10*8) return false; /* Require the full 10 bytes. */ + if(decoded < 10 * 8) return false; /* Require the full 10 bytes. */ /* CRC is just all bytes added mod 256. */ uint8_t crc = 0; - for (int j = 0; j < 9; j++) crc += raw[j]; - if (crc != raw[9]) return false; /* Require sane CRC. */ + for(int j = 0; j < 9; j++) crc += raw[j]; + if(crc != raw[9]) return false; /* Require sane CRC. */ - info->pulses_count = (off+10*8*2) - info->start_off; + info->pulses_count = (off + 10 * 8 * 2) - info->start_off; /* To convert the raw pressure to kPa, RTL433 uses 2.5, but is likely * wrong. Searching on Google for users experimenting with the value * reported, the value appears to be 2.75. */ - float kpa = (float)raw[7]*2.75; + float kpa = (float)raw[7] * 2.75; int temp_f = raw[8]; - int temp_c = (temp_f-32)*5/9; /* Convert Fahrenheit to Celsius. */ + int temp_c = (temp_f - 32) * 5 / 9; /* Convert Fahrenheit to Celsius. */ - fieldset_add_bytes(info->fieldset,"Tire ID",raw+4,3*2); - fieldset_add_float(info->fieldset,"Pressure kpa",kpa,2); - fieldset_add_int(info->fieldset,"Temperature C",temp_c,8); + fieldset_add_bytes(info->fieldset, "Tire ID", raw + 4, 3 * 2); + fieldset_add_float(info->fieldset, "Pressure kpa", kpa, 2); + fieldset_add_int(info->fieldset, "Temperature C", temp_c, 8); return true; } -ProtoViewDecoder SchraderEG53MA4TPMSDecoder = { - .name = "Schrader EG53MA4 TPMS", - .decode = decode, - .get_fields = NULL, - .build_message = NULL -}; +ProtoViewDecoder SchraderEG53MA4TPMSDecoder = + {.name = "Schrader EG53MA4 TPMS", .decode = decode, .get_fields = NULL, .build_message = NULL}; diff --git a/applications/plugins/protoview/protocols/tpms/toyota.c b/applications/plugins/protoview/protocols/tpms/toyota.c index b9dd1d959..b80af7647 100644 --- a/applications/plugins/protoview/protocols/tpms/toyota.c +++ b/applications/plugins/protoview/protocols/tpms/toyota.c @@ -24,40 +24,33 @@ #include "../../app.h" -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { - - if (numbits-6 < 64*2) return false; /* Ask for 64 bit of data (each bit +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { + if(numbits - 6 < 64 * 2) + return false; /* Ask for 64 bit of data (each bit is two symbols in the bitmap). */ - char *sync[] = { - "00111100", - "001111100", - "00111101", - "001111101", - NULL - }; + char* sync[] = {"00111100", "001111100", "00111101", "001111101", NULL}; int j; uint32_t off = 0; - for (j = 0; sync[j]; j++) { - off = bitmap_seek_bits(bits,numbytes,0,numbits,sync[j]); - if (off != BITMAP_SEEK_NOT_FOUND) { + for(j = 0; sync[j]; j++) { + off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync[j]); + if(off != BITMAP_SEEK_NOT_FOUND) { info->start_off = off; - off += strlen(sync[j])-2; + off += strlen(sync[j]) - 2; break; - } + } } - if (off == BITMAP_SEEK_NOT_FOUND) return false; + if(off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Toyota TPMS sync[%s] found", sync[j]); uint8_t raw[9]; - uint32_t decoded = - convert_from_diff_manchester(raw,sizeof(raw),bits,numbytes,off,true); + uint32_t decoded = convert_from_diff_manchester(raw, sizeof(raw), bits, numbytes, off, true); FURI_LOG_E(TAG, "Toyota TPMS decoded bits: %lu", decoded); - if (decoded < 8*9) return false; /* Require the full 8 bytes. */ - if (crc8(raw,8,0x80,7) != raw[8]) return false; /* Require sane CRC. */ + if(decoded < 8 * 9) return false; /* Require the full 8 bytes. */ + if(crc8(raw, 8, 0x80, 7) != raw[8]) return false; /* Require sane CRC. */ /* We detected a valid signal. However now info->start_off is actually * pointing to the sync part, not the preamble of alternating 0 and 1. @@ -65,25 +58,21 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView * for the decoder itself to fix the signal if neeeded, so that its * logical representation will be more accurate and better to save * and retransmit. */ - if (info->start_off >= 12) { + if(info->start_off >= 12) { info->start_off -= 12; - bitmap_set_pattern(bits,numbytes,info->start_off,"010101010101"); + bitmap_set_pattern(bits, numbytes, info->start_off, "010101010101"); } - info->pulses_count = (off+8*9*2) - info->start_off; + info->pulses_count = (off + 8 * 9 * 2) - info->start_off; - float psi = (float)((raw[4]&0x7f)<<1 | raw[5]>>7) * 0.25 - 7; - int temp = ((raw[5]&0x7f)<<1 | raw[6]>>7) - 40; + float psi = (float)((raw[4] & 0x7f) << 1 | raw[5] >> 7) * 0.25 - 7; + int temp = ((raw[5] & 0x7f) << 1 | raw[6] >> 7) - 40; - fieldset_add_bytes(info->fieldset,"Tire ID",raw,4*2); - fieldset_add_float(info->fieldset,"Pressure psi",psi,2); - fieldset_add_int(info->fieldset,"Temperature C",temp,8); + fieldset_add_bytes(info->fieldset, "Tire ID", raw, 4 * 2); + fieldset_add_float(info->fieldset, "Pressure psi", psi, 2); + fieldset_add_int(info->fieldset, "Temperature C", temp, 8); return true; } -ProtoViewDecoder ToyotaTPMSDecoder = { - .name = "Toyota TPMS", - .decode = decode, - .get_fields = NULL, - .build_message = NULL -}; +ProtoViewDecoder ToyotaTPMSDecoder = + {.name = "Toyota TPMS", .decode = decode, .get_fields = NULL, .build_message = NULL}; diff --git a/applications/plugins/protoview/raw_samples.c b/applications/plugins/protoview/raw_samples.c index f83cca361..54773f43f 100644 --- a/applications/plugins/protoview/raw_samples.c +++ b/applications/plugins/protoview/raw_samples.c @@ -8,15 +8,15 @@ #include "raw_samples.h" /* Allocate and initialize a samples buffer. */ -RawSamplesBuffer *raw_samples_alloc(void) { - RawSamplesBuffer *buf = malloc(sizeof(*buf)); +RawSamplesBuffer* raw_samples_alloc(void) { + RawSamplesBuffer* buf = malloc(sizeof(*buf)); buf->mutex = furi_mutex_alloc(FuriMutexTypeNormal); raw_samples_reset(buf); return buf; } /* Free a sample buffer. Should be called when the mutex is released. */ -void raw_samples_free(RawSamplesBuffer *s) { +void raw_samples_free(RawSamplesBuffer* s) { furi_mutex_free(s->mutex); free(s); } @@ -24,27 +24,27 @@ void raw_samples_free(RawSamplesBuffer *s) { /* This just set all the samples to zero and also resets the internal * index. There is no need to call it after raw_samples_alloc(), but only * when one wants to reset the whole buffer of samples. */ -void raw_samples_reset(RawSamplesBuffer *s) { - furi_mutex_acquire(s->mutex,FuriWaitForever); +void raw_samples_reset(RawSamplesBuffer* s) { + furi_mutex_acquire(s->mutex, FuriWaitForever); s->total = RAW_SAMPLES_NUM; s->idx = 0; s->short_pulse_dur = 0; - memset(s->samples,0,sizeof(s->samples)); + memset(s->samples, 0, sizeof(s->samples)); furi_mutex_release(s->mutex); } /* Set the raw sample internal index so that what is currently at * offset 'offset', will appear to be at 0 index. */ -void raw_samples_center(RawSamplesBuffer *s, uint32_t offset) { - s->idx = (s->idx+offset) % RAW_SAMPLES_NUM; +void raw_samples_center(RawSamplesBuffer* s, uint32_t offset) { + s->idx = (s->idx + offset) % RAW_SAMPLES_NUM; } /* Add the specified sample in the circular buffer. */ -void raw_samples_add(RawSamplesBuffer *s, bool level, uint32_t dur) { - furi_mutex_acquire(s->mutex,FuriWaitForever); +void raw_samples_add(RawSamplesBuffer* s, bool level, uint32_t dur) { + furi_mutex_acquire(s->mutex, FuriWaitForever); s->samples[s->idx].level = level; s->samples[s->idx].dur = dur; - s->idx = (s->idx+1) % RAW_SAMPLES_NUM; + s->idx = (s->idx + 1) % RAW_SAMPLES_NUM; furi_mutex_release(s->mutex); } @@ -56,28 +56,25 @@ void raw_samples_add(RawSamplesBuffer *s, bool level, uint32_t dur) { * * This function is a bit slower so the internal data sampling should * be performed with raw_samples_add(). */ -void raw_samples_add_or_update(RawSamplesBuffer *s, bool level, uint32_t dur) { - furi_mutex_acquire(s->mutex,FuriWaitForever); - uint32_t previdx = (s->idx-1) % RAW_SAMPLES_NUM; - if (s->samples[previdx].level == level && - s->samples[previdx].dur != 0) - { +void raw_samples_add_or_update(RawSamplesBuffer* s, bool level, uint32_t dur) { + furi_mutex_acquire(s->mutex, FuriWaitForever); + uint32_t previdx = (s->idx - 1) % RAW_SAMPLES_NUM; + if(s->samples[previdx].level == level && s->samples[previdx].dur != 0) { /* Update the last sample: it has the same level. */ s->samples[previdx].dur += dur; } else { /* Add a new sample. */ s->samples[s->idx].level = level; s->samples[s->idx].dur = dur; - s->idx = (s->idx+1) % RAW_SAMPLES_NUM; + s->idx = (s->idx + 1) % RAW_SAMPLES_NUM; } furi_mutex_release(s->mutex); } /* Get the sample from the buffer. It is possible to use out of range indexes * as 'idx' because the modulo operation will rewind back from the start. */ -void raw_samples_get(RawSamplesBuffer *s, uint32_t idx, bool *level, uint32_t *dur) -{ - furi_mutex_acquire(s->mutex,FuriWaitForever); +void raw_samples_get(RawSamplesBuffer* s, uint32_t idx, bool* level, uint32_t* dur) { + furi_mutex_acquire(s->mutex, FuriWaitForever); idx = (s->idx + idx) % RAW_SAMPLES_NUM; *level = s->samples[idx].level; *dur = s->samples[idx].dur; @@ -85,12 +82,12 @@ void raw_samples_get(RawSamplesBuffer *s, uint32_t idx, bool *level, uint32_t *d } /* Copy one buffer to the other, including current index. */ -void raw_samples_copy(RawSamplesBuffer *dst, RawSamplesBuffer *src) { - furi_mutex_acquire(src->mutex,FuriWaitForever); - furi_mutex_acquire(dst->mutex,FuriWaitForever); +void raw_samples_copy(RawSamplesBuffer* dst, RawSamplesBuffer* src) { + furi_mutex_acquire(src->mutex, FuriWaitForever); + furi_mutex_acquire(dst->mutex, FuriWaitForever); dst->idx = src->idx; dst->short_pulse_dur = src->short_pulse_dur; - memcpy(dst->samples,src->samples,sizeof(dst->samples)); + memcpy(dst->samples, src->samples, sizeof(dst->samples)); furi_mutex_release(src->mutex); furi_mutex_release(dst->mutex); } diff --git a/applications/plugins/protoview/raw_samples.h b/applications/plugins/protoview/raw_samples.h index 0b0422025..3493f07fd 100644 --- a/applications/plugins/protoview/raw_samples.h +++ b/applications/plugins/protoview/raw_samples.h @@ -4,16 +4,17 @@ /* Our circular buffer of raw samples, used in order to display * the signal. */ -#define RAW_SAMPLES_NUM 2048 /* Use a power of two: we take the modulo +#define RAW_SAMPLES_NUM \ + 2048 /* Use a power of two: we take the modulo of the index quite often to normalize inside the range, and division is slow. */ typedef struct RawSamplesBuffer { - FuriMutex *mutex; + FuriMutex* mutex; struct { - uint16_t level:1; - uint16_t dur:15; + uint16_t level : 1; + uint16_t dur : 15; } samples[RAW_SAMPLES_NUM]; - uint32_t idx; /* Current idx (next to write). */ + uint32_t idx; /* Current idx (next to write). */ uint32_t total; /* Total samples: same as RAW_SAMPLES_NUM, we provide this field for a cleaner interface with the user, but we always use RAW_SAMPLES_NUM when taking the modulo so @@ -22,11 +23,11 @@ typedef struct RawSamplesBuffer { uint32_t short_pulse_dur; /* Duration of the shortest pulse. */ } RawSamplesBuffer; -RawSamplesBuffer *raw_samples_alloc(void); -void raw_samples_reset(RawSamplesBuffer *s); -void raw_samples_center(RawSamplesBuffer *s, uint32_t offset); -void raw_samples_add(RawSamplesBuffer *s, bool level, uint32_t dur); -void raw_samples_add_or_update(RawSamplesBuffer *s, bool level, uint32_t dur); -void raw_samples_get(RawSamplesBuffer *s, uint32_t idx, bool *level, uint32_t *dur); -void raw_samples_copy(RawSamplesBuffer *dst, RawSamplesBuffer *src); -void raw_samples_free(RawSamplesBuffer *s); +RawSamplesBuffer* raw_samples_alloc(void); +void raw_samples_reset(RawSamplesBuffer* s); +void raw_samples_center(RawSamplesBuffer* s, uint32_t offset); +void raw_samples_add(RawSamplesBuffer* s, bool level, uint32_t dur); +void raw_samples_add_or_update(RawSamplesBuffer* s, bool level, uint32_t dur); +void raw_samples_get(RawSamplesBuffer* s, uint32_t idx, bool* level, uint32_t* dur); +void raw_samples_copy(RawSamplesBuffer* dst, RawSamplesBuffer* src); +void raw_samples_free(RawSamplesBuffer* s); diff --git a/applications/plugins/protoview/signal.c b/applications/plugins/protoview/signal.c index f4c5ebedf..a1c4b2b8f 100644 --- a/applications/plugins/protoview/signal.c +++ b/applications/plugins/protoview/signal.c @@ -3,7 +3,7 @@ #include "app.h" -bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info); +bool decode_signal(RawSamplesBuffer* s, uint64_t len, ProtoViewMsgInfo* info); /* ============================================================================= * Raw signal detection @@ -16,7 +16,7 @@ uint32_t duration_delta(uint32_t a, uint32_t b) { } /* Reset the current signal, so that a new one can be detected. */ -void reset_current_signal(ProtoViewApp *app) { +void reset_current_signal(ProtoViewApp* app) { app->signal_bestlen = 0; app->signal_offset = 0; app->signal_decoded = false; @@ -39,47 +39,47 @@ void reset_current_signal(ProtoViewApp *app) { * For instance Oregon2 sensors, in the case of protocol 2.1 will send * pulses of ~400us (RF on) VS ~580us (RF off). */ #define SEARCH_CLASSES 3 -uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) { +uint32_t search_coherent_signal(RawSamplesBuffer* s, uint32_t idx) { struct { - uint32_t dur[2]; /* dur[0] = low, dur[1] = high */ - uint32_t count[2]; /* Associated observed frequency. */ + uint32_t dur[2]; /* dur[0] = low, dur[1] = high */ + uint32_t count[2]; /* Associated observed frequency. */ } classes[SEARCH_CLASSES]; - memset(classes,0,sizeof(classes)); + memset(classes, 0, sizeof(classes)); uint32_t minlen = 30, maxlen = 4000; /* Depends on data rate, here we allow for high and low. */ uint32_t len = 0; /* Observed len of coherent samples. */ s->short_pulse_dur = 0; - for (uint32_t j = idx; j < idx+500; j++) { + for(uint32_t j = idx; j < idx + 500; j++) { bool level; uint32_t dur; raw_samples_get(s, j, &level, &dur); - if (dur < minlen || dur > maxlen) break; /* return. */ + if(dur < minlen || dur > maxlen) break; /* return. */ /* Let's see if it matches a class we already have or if we * can populate a new (yet empty) class. */ uint32_t k; - for (k = 0; k < SEARCH_CLASSES; k++) { - if (classes[k].count[level] == 0) { + for(k = 0; k < SEARCH_CLASSES; k++) { + if(classes[k].count[level] == 0) { classes[k].dur[level] = dur; classes[k].count[level] = 1; break; /* Sample accepted. */ } else { uint32_t classavg = classes[k].dur[level]; uint32_t count = classes[k].count[level]; - uint32_t delta = duration_delta(dur,classavg); + uint32_t delta = duration_delta(dur, classavg); /* Is the difference in duration between this signal and * the class we are inspecting less than a given percentage? * If so, accept this signal. */ - if (delta < classavg/5) { /* 100%/5 = 20%. */ + if(delta < classavg / 5) { /* 100%/5 = 20%. */ /* It is useful to compute the average of the class * we are observing. We know how many samples we got so * far, so we can recompute the average easily. * By always having a better estimate of the pulse len * we can avoid missing next samples in case the first * observed samples are too off. */ - classavg = ((classavg * count) + dur) / (count+1); + classavg = ((classavg * count) + dur) / (count + 1); classes[k].dur[level] = classavg; classes[k].count[level]++; break; /* Sample accepted. */ @@ -87,7 +87,7 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) { } } - if (k == SEARCH_CLASSES) break; /* No match, return. */ + if(k == SEARCH_CLASSES) break; /* No match, return. */ /* If we are here, we accepted this sample. Try with the next * one. */ @@ -97,14 +97,12 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) { /* Update the buffer setting the shortest pulse we found * among the three classes. This will be used when scaling * for visualization. */ - uint32_t short_dur[2] = {0,0}; - for (int j = 0; j < SEARCH_CLASSES; j++) { - for (int level = 0; level < 2; level++) { - if (classes[j].dur[level] == 0) continue; - if (classes[j].count[level] < 3) continue; - if (short_dur[level] == 0 || - short_dur[level] > classes[j].dur[level]) - { + uint32_t short_dur[2] = {0, 0}; + for(int j = 0; j < SEARCH_CLASSES; j++) { + for(int level = 0; level < 2; level++) { + if(classes[j].dur[level] == 0) continue; + if(classes[j].count[level] < 3) continue; + if(short_dur[level] == 0 || short_dur[level] > classes[j].dur[level]) { short_dur[level] = classes[j].dur[level]; } } @@ -113,33 +111,28 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) { /* Use the average between high and low short pulses duration. * Often they are a bit different, and using the average is more robust * when we do decoding sampling at short_pulse_dur intervals. */ - if (short_dur[0] == 0) short_dur[0] = short_dur[1]; - if (short_dur[1] == 0) short_dur[1] = short_dur[0]; - s->short_pulse_dur = (short_dur[0]+short_dur[1])/2; + if(short_dur[0] == 0) short_dur[0] = short_dur[1]; + if(short_dur[1] == 0) short_dur[1] = short_dur[0]; + s->short_pulse_dur = (short_dur[0] + short_dur[1]) / 2; return len; } /* Called when we detect a message. Just blinks when the message was * not decoded. Vibrates, too, when the message was correctly decoded. */ -void notify_signal_detected(ProtoViewApp *app, bool decoded) { +void notify_signal_detected(ProtoViewApp* app, bool decoded) { static const NotificationSequence decoded_seq = { &message_vibro_on, &message_green_255, &message_delay_50, &message_green_0, &message_vibro_off, - NULL - }; + NULL}; static const NotificationSequence unknown_seq = { - &message_red_255, - &message_delay_50, - &message_red_0, - NULL - }; + &message_red_255, &message_delay_50, &message_red_0, NULL}; - if (decoded) + if(decoded) notification_message(app->notification, &decoded_seq); else notification_message(app->notification, &unknown_seq); @@ -149,57 +142,59 @@ void notify_signal_detected(ProtoViewApp *app, bool decoded) { * in order to find a coherent signal. If a signal that does not appear to * be just noise is found, it is set in DetectedSamples global signal * buffer, that is what is rendered on the screen. */ -void scan_for_signal(ProtoViewApp *app, RawSamplesBuffer *source) { +void scan_for_signal(ProtoViewApp* app, RawSamplesBuffer* source) { /* We need to work on a copy: the source buffer may be populated * by the background thread receiving data. */ - RawSamplesBuffer *copy = raw_samples_alloc(); - raw_samples_copy(copy,source); + RawSamplesBuffer* copy = raw_samples_alloc(); + raw_samples_copy(copy, source); /* Try to seek on data that looks to have a regular high low high low * pattern. */ - uint32_t minlen = 18; /* Min run of coherent samples. With less + uint32_t minlen = 18; /* Min run of coherent samples. With less than a few samples it's very easy to mistake noise for signal. */ uint32_t i = 0; - while (i < copy->total-1) { - uint32_t thislen = search_coherent_signal(copy,i); + while(i < copy->total - 1) { + uint32_t thislen = search_coherent_signal(copy, i); /* For messages that are long enough, attempt decoding. */ - if (thislen > minlen) { + if(thislen > minlen) { /* Allocate the message information that some decoder may * fill, in case it is able to decode a message. */ - ProtoViewMsgInfo *info = malloc(sizeof(ProtoViewMsgInfo)); - init_msg_info(info,app); + ProtoViewMsgInfo* info = malloc(sizeof(ProtoViewMsgInfo)); + init_msg_info(info, app); info->short_pulse_dur = copy->short_pulse_dur; uint32_t saved_idx = copy->idx; /* Save index, see later. */ /* decode_signal() expects the detected signal to start * from index zero .*/ - raw_samples_center(copy,i); - bool decoded = decode_signal(copy,thislen,info); + raw_samples_center(copy, i); + bool decoded = decode_signal(copy, thislen, info); copy->idx = saved_idx; /* Restore the index as we are scanning the signal in the loop. */ /* Accept this signal as the new signal if either it's longer * than the previous undecoded one, or the previous one was * unknown and this is decoded. */ - if ((thislen > app->signal_bestlen && app->signal_decoded == false) - || (app->signal_decoded == false && decoded)) - { + if((thislen > app->signal_bestlen && app->signal_decoded == false) || + (app->signal_decoded == false && decoded)) { free_msg_info(app->msg_info); app->msg_info = info; app->signal_bestlen = thislen; app->signal_decoded = decoded; - raw_samples_copy(DetectedSamples,copy); - raw_samples_center(DetectedSamples,i); - FURI_LOG_E(TAG, "===> Displayed sample updated (%d samples %lu us)", - (int)thislen, DetectedSamples->short_pulse_dur); + raw_samples_copy(DetectedSamples, copy); + raw_samples_center(DetectedSamples, i); + FURI_LOG_E( + TAG, + "===> Displayed sample updated (%d samples %lu us)", + (int)thislen, + DetectedSamples->short_pulse_dur); - adjust_raw_view_scale(app,DetectedSamples->short_pulse_dur); - notify_signal_detected(app,decoded); + adjust_raw_view_scale(app, DetectedSamples->short_pulse_dur); + notify_signal_detected(app, decoded); } else { /* If the structure was not filled, discard it. Otherwise * now the owner is app->msg_info. */ @@ -227,38 +222,42 @@ void scan_for_signal(ProtoViewApp *app, RawSamplesBuffer *source) { /* Set the 'bitpos' bit to value 'val', in the specified bitmap * 'b' of len 'blen'. * Out of range bits will silently be discarded. */ -void bitmap_set(uint8_t *b, uint32_t blen, uint32_t bitpos, bool val) { - uint32_t byte = bitpos/8; - uint32_t bit = 7-(bitpos&7); - if (byte >= blen) return; - if (val) - b[byte] |= 1<= blen) return; + if(val) + b[byte] |= 1 << bit; else - b[byte] &= ~(1<= blen) return 0; - return (b[byte] & (1<= blen) return 0; + return (b[byte] & (1 << bit)) != 0; } /* Copy 'count' bits from the bitmap 's' of 'slen' total bytes, to the * bitmap 'd' of 'dlen' total bytes. The bits are copied starting from * offset 'soff' of the source bitmap to the offset 'doff' of the * destination bitmap. */ -void bitmap_copy(uint8_t *d, uint32_t dlen, uint32_t doff, - uint8_t *s, uint32_t slen, uint32_t soff, - uint32_t count) -{ +void bitmap_copy( + uint8_t* d, + uint32_t dlen, + uint32_t doff, + uint8_t* s, + uint32_t slen, + uint32_t soff, + uint32_t count) { /* If we are byte-aligned in both source and destination, use a fast * path for the number of bytes we can consume this way. */ - if ((doff & 7) == 0 && (soff & 7) == 0) { - uint32_t didx = doff/8; - uint32_t sidx = soff/8; + if((doff & 7) == 0 && (soff & 7) == 0) { + uint32_t didx = doff / 8; + uint32_t sidx = soff / 8; while(count > 8 && didx < dlen && sidx < slen) { d[didx++] = s[sidx++]; count -= 8; @@ -271,9 +270,9 @@ void bitmap_copy(uint8_t *d, uint32_t dlen, uint32_t doff, /* Copy the bits needed to reach an offset where we can copy * two half bytes of src to a full byte of destination. */ - while(count > 8 && (doff&7) != 0) { - bool bit = bitmap_get(s,slen,soff++); - bitmap_set(d,dlen,doff++,bit); + while(count > 8 && (doff & 7) != 0) { + bool bit = bitmap_get(s, slen, soff++); + bitmap_set(d, dlen, doff++, bit); count--; } @@ -316,13 +315,12 @@ void bitmap_copy(uint8_t *d, uint32_t dlen, uint32_t doff, * src[2] << 5, that is "WORLDS!!" >> 5 = ".....WOR" * That is "HELLOWOR" */ - if (count > 8) { + if(count > 8) { uint8_t skew = soff % 8; /* Don't worry, compiler will optimize. */ - uint32_t didx = doff/8; - uint32_t sidx = soff/8; + uint32_t didx = doff / 8; + uint32_t sidx = soff / 8; while(count > 8 && didx < dlen && sidx < slen) { - d[didx] = ((s[sidx] << skew) | - (s[sidx+1] >> (8-skew))); + d[didx] = ((s[sidx] << skew) | (s[sidx + 1] >> (8 - skew))); sidx++; didx++; soff += 8; @@ -334,8 +332,8 @@ void bitmap_copy(uint8_t *d, uint32_t dlen, uint32_t doff, /* Here count is guaranteed to be < 8. * Copy the final bits bit by bit. */ while(count) { - bool bit = bitmap_get(s,slen,soff++); - bitmap_set(d,dlen,doff++,bit); + bool bit = bitmap_get(s, slen, soff++); + bitmap_set(d, dlen, doff++, bit); count--; } } @@ -343,15 +341,15 @@ void bitmap_copy(uint8_t *d, uint32_t dlen, uint32_t doff, /* We decode bits assuming the first bit we receive is the MSB * (see bitmap_set/get functions). Certain devices send data * encoded in the reverse way. */ -void bitmap_reverse_bytes_bits(uint8_t *p, uint32_t len) { - for (uint32_t j = 0; j < len; j++) { +void bitmap_reverse_bytes_bits(uint8_t* p, uint32_t len) { + for(uint32_t j = 0; j < len; j++) { uint32_t b = p[j]; /* Step 1: swap the two nibbles: 12345678 -> 56781234 */ - b = (b&0xf0)>>4 | (b&0x0f)<<4; + b = (b & 0xf0) >> 4 | (b & 0x0f) << 4; /* Step 2: swap adjacent pairs : 56781234 -> 78563412 */ - b = (b&0xcc)>>2 | (b&0x33)<<2; + b = (b & 0xcc) >> 2 | (b & 0x33) << 2; /* Step 3: swap adjacent bits : 78563412 -> 87654321 */ - b = (b&0xaa)>>1 | (b&0x55)<<1; + b = (b & 0xaa) >> 1 | (b & 0x55) << 1; p[j] = b; } } @@ -359,10 +357,10 @@ void bitmap_reverse_bytes_bits(uint8_t *p, uint32_t len) { /* Return true if the specified sequence of bits, provided as a string in the * form "11010110..." is found in the 'b' bitmap of 'blen' bits at 'bitpos' * position. */ -bool bitmap_match_bits(uint8_t *b, uint32_t blen, uint32_t bitpos, const char *bits) { - for (size_t j = 0; bits[j]; j++) { +bool bitmap_match_bits(uint8_t* b, uint32_t blen, uint32_t bitpos, const char* bits) { + for(size_t j = 0; bits[j]; j++) { bool expected = (bits[j] == '1') ? true : false; - if (bitmap_get(b,blen,bitpos+j) != expected) return false; + if(bitmap_get(b, blen, bitpos + j) != expected) return false; } return true; } @@ -375,12 +373,17 @@ bool bitmap_match_bits(uint8_t *b, uint32_t blen, uint32_t bitpos, const char *b * Note: there are better algorithms, such as Boyer-Moore. Here we hope that * for the kind of patterns we search we'll have a lot of early stops so * we use a vanilla approach. */ -uint32_t bitmap_seek_bits(uint8_t *b, uint32_t blen, uint32_t startpos, uint32_t maxbits, const char *bits) { - uint32_t endpos = startpos+blen*8; - uint32_t end2 = startpos+maxbits; - if (end2 < endpos) endpos = end2; - for (uint32_t j = startpos; j < endpos; j++) - if (bitmap_match_bits(b,blen,j,bits)) return j; +uint32_t bitmap_seek_bits( + uint8_t* b, + uint32_t blen, + uint32_t startpos, + uint32_t maxbits, + const char* bits) { + uint32_t endpos = startpos + blen * 8; + uint32_t end2 = startpos + maxbits; + if(end2 < endpos) endpos = end2; + for(uint32_t j = startpos; j < endpos; j++) + if(bitmap_match_bits(b, blen, j, bits)) return j; return BITMAP_SEEK_NOT_FOUND; } @@ -391,10 +394,10 @@ uint32_t bitmap_seek_bits(uint8_t *b, uint32_t blen, uint32_t startpos, uint32_t * This function is useful in order to set the test vectors in the protocol * decoders, to see if the decoding works regardless of the fact we are able * to actually receive a given signal. */ -void bitmap_set_pattern(uint8_t *b, uint32_t blen, uint32_t off, const char *pat) { +void bitmap_set_pattern(uint8_t* b, uint32_t blen, uint32_t off, const char* pat) { uint32_t i = 0; while(pat[i]) { - bitmap_set(b,blen,i+off,pat[i] == '1'); + bitmap_set(b, blen, i + off, pat[i] == '1'); i++; } } @@ -426,31 +429,36 @@ void bitmap_set_pattern(uint8_t *b, uint32_t blen, uint32_t off, const char *pat * bits set into the buffer 'b'. The 'rate' argument, in microseconds, is * the detected short-pulse duration. We expect the line code to be * meaningful when interpreted at multiples of 'rate'. */ -uint32_t convert_signal_to_bits(uint8_t *b, uint32_t blen, RawSamplesBuffer *s, uint32_t idx, uint32_t count, uint32_t rate) { - if (rate == 0) return 0; /* We can't perform the conversion. */ +uint32_t convert_signal_to_bits( + uint8_t* b, + uint32_t blen, + RawSamplesBuffer* s, + uint32_t idx, + uint32_t count, + uint32_t rate) { + if(rate == 0) return 0; /* We can't perform the conversion. */ uint32_t bitpos = 0; - for (uint32_t j = 0; j < count; j++) { + for(uint32_t j = 0; j < count; j++) { uint32_t dur; bool level; - raw_samples_get(s, j+idx, &level, &dur); + raw_samples_get(s, j + idx, &level, &dur); uint32_t numbits = dur / rate; /* full bits that surely fit. */ - uint32_t rest = dur % rate; /* How much we are left with. */ - if (rest > rate/2) numbits++; /* There is another one. */ + uint32_t rest = dur % rate; /* How much we are left with. */ + if(rest > rate / 2) numbits++; /* There is another one. */ /* Limit how much a single sample can spawn. There are likely no * protocols doing such long pulses when the rate is low. */ - if (numbits > 1024) numbits = 1024; + if(numbits > 1024) numbits = 1024; - if (0) /* Super verbose, so not under the DEBUG_MSG define. */ - FURI_LOG_E(TAG, "%lu converted into %lu (%d) bits", - dur,numbits,(int)level); + if(0) /* Super verbose, so not under the DEBUG_MSG define. */ + FURI_LOG_E(TAG, "%lu converted into %lu (%d) bits", dur, numbits, (int)level); /* If the signal is too short, let's claim it an interference * and ignore it completely. */ - if (numbits == 0) continue; + if(numbits == 0) continue; - while(numbits--) bitmap_set(b,blen,bitpos++,level); + while(numbits--) bitmap_set(b, blen, bitpos++, level); } return bitpos; } @@ -467,23 +475,29 @@ uint32_t convert_signal_to_bits(uint8_t *b, uint32_t blen, RawSamplesBuffer *s, * specified in bytes by the caller, via the 'len' parameters). * * The decoding starts at the specified offset (in bits) 'off'. */ -uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t off, const char *zero_pattern, const char *one_pattern) -{ +uint32_t convert_from_line_code( + uint8_t* buf, + uint64_t buflen, + uint8_t* bits, + uint32_t len, + uint32_t off, + const char* zero_pattern, + const char* one_pattern) { uint32_t decoded = 0; /* Number of bits extracted. */ len *= 8; /* Convert bytes to bits. */ while(off < len) { bool bitval; - if (bitmap_match_bits(bits,len,off,zero_pattern)) { + if(bitmap_match_bits(bits, len, off, zero_pattern)) { bitval = false; off += strlen(zero_pattern); - } else if (bitmap_match_bits(bits,len,off,one_pattern)) { + } else if(bitmap_match_bits(bits, len, off, one_pattern)) { bitval = true; off += strlen(one_pattern); } else { break; } - bitmap_set(buf,buflen,decoded++,bitval); - if (decoded/8 == buflen) break; /* No space left on target buffer. */ + bitmap_set(buf, buflen, decoded++, bitval); + if(decoded / 8 == buflen) break; /* No space left on target buffer. */ } return decoded; } @@ -494,17 +508,22 @@ uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, ui * in differential codings the next bits depend on the previous one. * * Parameters and return values are like convert_from_line_code(). */ -uint32_t convert_from_diff_manchester(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t off, bool previous) -{ +uint32_t convert_from_diff_manchester( + uint8_t* buf, + uint64_t buflen, + uint8_t* bits, + uint32_t len, + uint32_t off, + bool previous) { uint32_t decoded = 0; len *= 8; /* Conver to bits. */ - for (uint32_t j = off; j < len; j += 2) { - bool b0 = bitmap_get(bits,len,j); - bool b1 = bitmap_get(bits,len,j+1); - if (b0 == previous) break; /* Each new bit must switch value. */ - bitmap_set(buf,buflen,decoded++,b0 == b1); + for(uint32_t j = off; j < len; j += 2) { + bool b0 = bitmap_get(bits, len, j); + bool b1 = bitmap_get(bits, len, j + 1); + if(b0 == previous) break; /* Each new bit must switch value. */ + bitmap_set(buf, buflen, decoded++, b0 == b1); previous = b1; - if (decoded/8 == buflen) break; /* No space left on target buffer. */ + if(decoded / 8 == buflen) break; /* No space left on target buffer. */ } return decoded; } @@ -522,22 +541,21 @@ extern ProtoViewDecoder CitroenTPMSDecoder; extern ProtoViewDecoder FordTPMSDecoder; extern ProtoViewDecoder KeeloqDecoder; -ProtoViewDecoder *Decoders[] = { - &Oregon2Decoder, /* Oregon sensors v2.1 protocol. */ - &B4B1Decoder, /* PT, SC, ... 24 bits remotes. */ - &RenaultTPMSDecoder, /* Renault TPMS. */ - &ToyotaTPMSDecoder, /* Toyota TPMS. */ - &SchraderTPMSDecoder, /* Schrader TPMS. */ - &SchraderEG53MA4TPMSDecoder, /* Schrader EG53MA4 TPMS. */ - &CitroenTPMSDecoder, /* Citroen TPMS. */ - &FordTPMSDecoder, /* Ford TPMS. */ - &KeeloqDecoder, /* Keeloq remote. */ - NULL -}; +ProtoViewDecoder* Decoders[] = { + &Oregon2Decoder, /* Oregon sensors v2.1 protocol. */ + &B4B1Decoder, /* PT, SC, ... 24 bits remotes. */ + &RenaultTPMSDecoder, /* Renault TPMS. */ + &ToyotaTPMSDecoder, /* Toyota TPMS. */ + &SchraderTPMSDecoder, /* Schrader TPMS. */ + &SchraderEG53MA4TPMSDecoder, /* Schrader EG53MA4 TPMS. */ + &CitroenTPMSDecoder, /* Citroen TPMS. */ + &FordTPMSDecoder, /* Ford TPMS. */ + &KeeloqDecoder, /* Keeloq remote. */ + NULL}; /* Free the message info and allocated data. */ -void free_msg_info(ProtoViewMsgInfo *i) { - if (i == NULL) return; +void free_msg_info(ProtoViewMsgInfo* i) { + if(i == NULL) return; fieldset_free(i->fieldset); free(i->bits); free(i); @@ -545,9 +563,9 @@ void free_msg_info(ProtoViewMsgInfo *i) { /* Reset the message info structure before passing it to the decoding * functions. */ -void init_msg_info(ProtoViewMsgInfo *i, ProtoViewApp *app) { +void init_msg_info(ProtoViewMsgInfo* i, ProtoViewApp* app) { UNUSED(app); - memset(i,0,sizeof(ProtoViewMsgInfo)); + memset(i, 0, sizeof(ProtoViewMsgInfo)); i->bits = NULL; i->fieldset = fieldset_new(); } @@ -556,23 +574,29 @@ void init_msg_info(ProtoViewMsgInfo *i, ProtoViewApp *app) { * to a bitstream, and the calls the protocol specific functions for * decoding. If the signal was decoded correctly by some protocol, true * is returned. Otherwise false is returned. */ -bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) { - uint32_t bitmap_bits_size = 4096*8; - uint32_t bitmap_size = bitmap_bits_size/8; +bool decode_signal(RawSamplesBuffer* s, uint64_t len, ProtoViewMsgInfo* info) { + uint32_t bitmap_bits_size = 4096 * 8; + uint32_t bitmap_size = bitmap_bits_size / 8; /* We call the decoders with an offset a few samples before the actual * signal detected and for a len of a few bits after its end. */ uint32_t before_samples = 32; uint32_t after_samples = 100; - uint8_t *bitmap = malloc(bitmap_size); - uint32_t bits = convert_signal_to_bits(bitmap,bitmap_size,s,-before_samples,len+before_samples+after_samples,s->short_pulse_dur); + uint8_t* bitmap = malloc(bitmap_size); + uint32_t bits = convert_signal_to_bits( + bitmap, + bitmap_size, + s, + -before_samples, + len + before_samples + after_samples, + s->short_pulse_dur); - if (DEBUG_MSG) { /* Useful for debugging purposes. Don't remove. */ - char *str = malloc(1024); + if(DEBUG_MSG) { /* Useful for debugging purposes. Don't remove. */ + char* str = malloc(1024); uint32_t j; - for (j = 0; j < bits && j < 1023; j++) { - str[j] = bitmap_get(bitmap,bitmap_size,j) ? '1' : '0'; + for(j = 0; j < bits && j < 1023; j++) { + str[j] = bitmap_get(bitmap, bitmap_size, j) ? '1' : '0'; } str[j] = 0; FURI_LOG_E(TAG, "%lu bits sampled: %s", bits, str); @@ -585,18 +609,17 @@ bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) { bool decoded = false; while(Decoders[j]) { uint32_t start_time = furi_get_tick(); - decoded = Decoders[j]->decode(bitmap,bitmap_size,bits,info); + decoded = Decoders[j]->decode(bitmap, bitmap_size, bits, info); uint32_t delta = furi_get_tick() - start_time; - FURI_LOG_E(TAG, "Decoder %s took %lu ms", - Decoders[j]->name, (unsigned long)delta); - if (decoded) { + FURI_LOG_E(TAG, "Decoder %s took %lu ms", Decoders[j]->name, (unsigned long)delta); + if(decoded) { info->decoder = Decoders[j]; break; } j++; } - if (!decoded) { + if(!decoded) { FURI_LOG_E(TAG, "No decoding possible"); } else { FURI_LOG_E(TAG, "+++ Decoded %s", info->decoder->name); @@ -604,12 +627,17 @@ bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) { * with the decoded signal. The decoder may not implement offset/len * filling of the structure. In such case we have no info and * pulses_count will be set to zero. */ - if (info->pulses_count) { - info->bits_bytes = (info->pulses_count+7)/8; // Round to full byte. + if(info->pulses_count) { + info->bits_bytes = (info->pulses_count + 7) / 8; // Round to full byte. info->bits = malloc(info->bits_bytes); - bitmap_copy(info->bits,info->bits_bytes,0, - bitmap,bitmap_size,info->start_off, - info->pulses_count); + bitmap_copy( + info->bits, + info->bits_bytes, + 0, + bitmap, + bitmap_size, + info->start_off, + info->pulses_count); } } free(bitmap); diff --git a/applications/plugins/protoview/signal_file.c b/applications/plugins/protoview/signal_file.c index 31c8726fb..c60a6a181 100644 --- a/applications/plugins/protoview/signal_file.c +++ b/applications/plugins/protoview/signal_file.c @@ -13,57 +13,56 @@ * but it's logical representation stored in the app->msg_info bitmap, where * each 1 or 0 means a puls or gap for the specified short pulse duration time * (te). */ -bool save_signal(ProtoViewApp *app, const char *filename) { +bool save_signal(ProtoViewApp* app, const char* filename) { /* We have a message at all? */ - if (app->msg_info == NULL || app->msg_info->pulses_count == 0) return false; - - Storage *storage = furi_record_open(RECORD_STORAGE); - FlipperFormat *file = flipper_format_file_alloc(storage); - Stream *stream = flipper_format_get_raw_stream(file); - FuriString *file_content = NULL; + if(app->msg_info == NULL || app->msg_info->pulses_count == 0) return false; + + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* file = flipper_format_file_alloc(storage); + Stream* stream = flipper_format_get_raw_stream(file); + FuriString* file_content = NULL; bool success = true; - if (flipper_format_file_open_always(file, filename)) { + if(flipper_format_file_open_always(file, filename)) { /* Write the file header. */ - FuriString *file_content = furi_string_alloc(); - const char *preset_id = ProtoViewModulations[app->modulation].id; + FuriString* file_content = furi_string_alloc(); + const char* preset_id = ProtoViewModulations[app->modulation].id; - furi_string_printf(file_content, - "Filetype: Flipper SubGhz RAW File\n" - "Version: 1\n" - "Frequency: %ld\n" - "Preset: %s\n", - app->frequency, - preset_id ? preset_id : "FuriHalSubGhzPresetCustom"); + furi_string_printf( + file_content, + "Filetype: Flipper SubGhz RAW File\n" + "Version: 1\n" + "Frequency: %ld\n" + "Preset: %s\n", + app->frequency, + preset_id ? preset_id : "FuriHalSubGhzPresetCustom"); /* For custom modulations, we need to emit a set of registers. */ - if (preset_id == NULL) { - FuriString *custom = furi_string_alloc(); - uint8_t *regs = ProtoViewModulations[app->modulation].custom; - furi_string_printf(custom, + if(preset_id == NULL) { + FuriString* custom = furi_string_alloc(); + uint8_t* regs = ProtoViewModulations[app->modulation].custom; + furi_string_printf( + custom, "Custom_preset_module: CC1101\n" - "Custom_preset_data: "); - for (int j = 0; regs[j]; j += 2) { - furi_string_cat_printf(custom, "%02X %02X ", - (int)regs[j], (int)regs[j+1]); + "Custom_preset_data: "); + for(int j = 0; regs[j]; j += 2) { + furi_string_cat_printf(custom, "%02X %02X ", (int)regs[j], (int)regs[j + 1]); } size_t len = furi_string_size(file_content); - furi_string_set_char(custom,len-1,'\n'); - furi_string_cat(file_content,custom); + furi_string_set_char(custom, len - 1, '\n'); + furi_string_cat(file_content, custom); furi_string_free(custom); } /* We always save raw files. */ - furi_string_cat_printf(file_content, - "Protocol: RAW\n" - "RAW_Data: -10000\n"); // Start with 10 ms of gap + furi_string_cat_printf( + file_content, + "Protocol: RAW\n" + "RAW_Data: -10000\n"); // Start with 10 ms of gap /* Write header. */ size_t len = furi_string_size(file_content); - if (stream_write(stream, - (uint8_t*) furi_string_get_cstr(file_content), len) - != len) - { + if(stream_write(stream, (uint8_t*)furi_string_get_cstr(file_content), len) != len) { FURI_LOG_W(TAG, "Short write to file"); success = false; goto write_err; @@ -76,15 +75,13 @@ bool save_signal(ProtoViewApp *app, const char *filename) { uint32_t this_line_samples = 0; uint32_t max_line_samples = 100; uint32_t idx = 0; // Iindex in the signal bitmap. - ProtoViewMsgInfo *i = app->msg_info; + ProtoViewMsgInfo* i = app->msg_info; while(idx < i->pulses_count) { - bool level = bitmap_get(i->bits,i->bits_bytes,idx); + bool level = bitmap_get(i->bits, i->bits_bytes, idx); uint32_t te_times = 1; idx++; /* Count the duration of the current pulse/gap. */ - while(idx < i->pulses_count && - bitmap_get(i->bits,i->bits_bytes,idx) == level) - { + while(idx < i->pulses_count && bitmap_get(i->bits, i->bits_bytes, idx) == level) { te_times++; idx++; } @@ -92,32 +89,29 @@ bool save_signal(ProtoViewApp *app, const char *filename) { // next gap or pulse. int32_t dur = (int32_t)i->short_pulse_dur * te_times; - if (level == 0) dur = -dur; /* Negative is gap in raw files. */ + if(level == 0) dur = -dur; /* Negative is gap in raw files. */ /* Emit the sample. If this is the first sample of the line, * also emit the RAW_Data: field. */ - if (this_line_samples == 0) - furi_string_cat_printf(file_content,"RAW_Data: "); - furi_string_cat_printf(file_content,"%d ",(int)dur); + if(this_line_samples == 0) furi_string_cat_printf(file_content, "RAW_Data: "); + furi_string_cat_printf(file_content, "%d ", (int)dur); this_line_samples++; /* Store the current set of samples on disk, when we reach a * given number or the end of the signal. */ bool end_reached = (idx == i->pulses_count); - if (this_line_samples == max_line_samples || end_reached) { + if(this_line_samples == max_line_samples || end_reached) { /* If that's the end, terminate the signal with a long * gap. */ - if (end_reached) furi_string_cat_printf(file_content,"-10000 "); + if(end_reached) furi_string_cat_printf(file_content, "-10000 "); /* We always have a trailing space in the last sample. Make it * a newline. */ size_t len = furi_string_size(file_content); - furi_string_set_char(file_content,len-1,'\n'); + furi_string_set_char(file_content, len - 1, '\n'); - if (stream_write(stream, - (uint8_t*) furi_string_get_cstr(file_content), - len) != len) - { + if(stream_write(stream, (uint8_t*)furi_string_get_cstr(file_content), len) != + len) { FURI_LOG_W(TAG, "Short write to file"); success = false; goto write_err; @@ -136,6 +130,6 @@ bool save_signal(ProtoViewApp *app, const char *filename) { write_err: furi_record_close(RECORD_STORAGE); flipper_format_free(file); - if (file_content != NULL) furi_string_free(file_content); + if(file_content != NULL) furi_string_free(file_content); return success; } diff --git a/applications/plugins/protoview/ui.c b/applications/plugins/protoview/ui.c index 8badab5bf..b0251f09f 100644 --- a/applications/plugins/protoview/ui.c +++ b/applications/plugins/protoview/ui.c @@ -10,36 +10,31 @@ /* Return the ID of the currently selected subview, of the current * view. */ -int ui_get_current_subview(ProtoViewApp *app) { +int ui_get_current_subview(ProtoViewApp* app) { return app->current_subview[app->current_view]; } /* Called by view rendering callback that has subviews, to show small triangles * facing down/up if there are other subviews the user can access with up * and down. */ -void ui_show_available_subviews(Canvas *canvas, ProtoViewApp *app, - int last_subview) -{ +void ui_show_available_subviews(Canvas* canvas, ProtoViewApp* app, int last_subview) { int subview = ui_get_current_subview(app); - if (subview != 0) - canvas_draw_triangle(canvas,120,5,8,5,CanvasDirectionBottomToTop); - if (subview != last_subview-1) - canvas_draw_triangle(canvas,120,59,8,5,CanvasDirectionTopToBottom); + if(subview != 0) canvas_draw_triangle(canvas, 120, 5, 8, 5, CanvasDirectionBottomToTop); + if(subview != last_subview - 1) + canvas_draw_triangle(canvas, 120, 59, 8, 5, CanvasDirectionTopToBottom); } /* Handle up/down keys when we are in a subview. If the function catched * such keypress, it returns true, so that the actual view input callback * knows it can just return ASAP without doing anything. */ -bool ui_process_subview_updown(ProtoViewApp *app, InputEvent input, int last_subview) { +bool ui_process_subview_updown(ProtoViewApp* app, InputEvent input, int last_subview) { int subview = ui_get_current_subview(app); - if (input.type == InputTypePress) { - if (input.key == InputKeyUp) { - if (subview != 0) - app->current_subview[app->current_view]--; + if(input.type == InputTypePress) { + if(input.key == InputKeyUp) { + if(subview != 0) app->current_subview[app->current_view]--; return true; - } else if (input.key == InputKeyDown) { - if (subview != last_subview-1) - app->current_subview[app->current_view]++; + } else if(input.key == InputKeyDown) { + if(subview != last_subview - 1) app->current_subview[app->current_view]++; return true; } } @@ -62,16 +57,18 @@ bool ui_process_subview_updown(ProtoViewApp *app, InputEvent input, int last_sub * * Note: if the buffer is not a null-termined zero string, what it contains will * be used as initial input for the user. */ -void ui_show_keyboard(ProtoViewApp *app, char *buffer, uint32_t buflen, - void (*done_callback)(void*)) -{ +void ui_show_keyboard( + ProtoViewApp* app, + char* buffer, + uint32_t buflen, + void (*done_callback)(void*)) { app->show_text_input = true; app->text_input_buffer = buffer; app->text_input_buffer_len = buflen; app->text_input_done_callback = done_callback; } -void ui_dismiss_keyboard(ProtoViewApp *app) { +void ui_dismiss_keyboard(ProtoViewApp* app) { view_dispatcher_stop(app->view_dispatcher); } @@ -79,24 +76,24 @@ void ui_dismiss_keyboard(ProtoViewApp *app) { /* Set an alert message to be shown over any currently active view, for * the specified amount of time of 'ttl' milliseconds. */ -void ui_show_alert(ProtoViewApp *app, const char *text, uint32_t ttl) { +void ui_show_alert(ProtoViewApp* app, const char* text, uint32_t ttl) { app->alert_dismiss_time = furi_get_tick() + furi_ms_to_ticks(ttl); - snprintf(app->alert_text,ALERT_MAX_LEN,"%s",text); + snprintf(app->alert_text, ALERT_MAX_LEN, "%s", text); } /* Cancel the alert before its time has elapsed. */ -void ui_dismiss_alert(ProtoViewApp *app) { +void ui_dismiss_alert(ProtoViewApp* app) { app->alert_dismiss_time = 0; } /* Show the alert if an alert is set. This is called after the currently * active view displayed its stuff, so we overwrite the screen with the * alert message. */ -void ui_draw_alert_if_needed(Canvas *canvas, ProtoViewApp *app) { - if (app->alert_dismiss_time == 0) { +void ui_draw_alert_if_needed(Canvas* canvas, ProtoViewApp* app) { + if(app->alert_dismiss_time == 0) { /* No active alert. */ return; - } else if (app->alert_dismiss_time < furi_get_tick()) { + } else if(app->alert_dismiss_time < furi_get_tick()) { /* Alert just expired. */ ui_dismiss_alert(app); return; @@ -106,41 +103,43 @@ void ui_draw_alert_if_needed(Canvas *canvas, ProtoViewApp *app) { canvas_set_font(canvas, FontPrimary); uint8_t w = canvas_string_width(canvas, app->alert_text); uint8_t h = 8; // Font height. - uint8_t text_x = 64-(w/2); - uint8_t text_y = 32+4; + uint8_t text_x = 64 - (w / 2); + uint8_t text_y = 32 + 4; uint8_t padding = 3; - canvas_set_color(canvas,ColorBlack); - canvas_draw_box(canvas,text_x-padding,text_y-padding-h,w+padding*2,h+padding*2); - canvas_set_color(canvas,ColorWhite); - canvas_draw_box(canvas,text_x-padding+1,text_y-padding-h+1,w+padding*2-2,h+padding*2-2); - canvas_set_color(canvas,ColorBlack); - canvas_draw_str(canvas,text_x,text_y,app->alert_text); + canvas_set_color(canvas, ColorBlack); + canvas_draw_box( + canvas, text_x - padding, text_y - padding - h, w + padding * 2, h + padding * 2); + canvas_set_color(canvas, ColorWhite); + canvas_draw_box( + canvas, + text_x - padding + 1, + text_y - padding - h + 1, + w + padding * 2 - 2, + h + padding * 2 - 2); + canvas_set_color(canvas, ColorBlack); + canvas_draw_str(canvas, text_x, text_y, app->alert_text); } /* =========================== Canvas extensions ============================ */ -void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const char* str, Color text_color, Color border_color) -{ +void canvas_draw_str_with_border( + Canvas* canvas, + uint8_t x, + uint8_t y, + const char* str, + Color text_color, + Color border_color) { struct { - uint8_t x; uint8_t y; - } dir[8] = { - {-1,-1}, - {0,-1}, - {1,-1}, - {1,0}, - {1,1}, - {0,1}, - {-1,1}, - {-1,0} - }; + uint8_t x; + uint8_t y; + } dir[8] = {{-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}}; /* Rotate in all the directions writing the same string to create a * border, then write the actual string in the other color in the * middle. */ canvas_set_color(canvas, border_color); - for (int j = 0; j < 8; j++) - canvas_draw_str(canvas,x+dir[j].x,y+dir[j].y,str); + for(int j = 0; j < 8; j++) canvas_draw_str(canvas, x + dir[j].x, y + dir[j].y, str); canvas_set_color(canvas, text_color); - canvas_draw_str(canvas,x,y,str); + canvas_draw_str(canvas, x, y, str); canvas_set_color(canvas, ColorBlack); } diff --git a/applications/plugins/protoview/view_build.c b/applications/plugins/protoview/view_build.c index fd276b61d..955855902 100644 --- a/applications/plugins/protoview/view_build.c +++ b/applications/plugins/protoview/view_build.c @@ -3,39 +3,38 @@ #include "app.h" -extern ProtoViewDecoder *Decoders[]; // Defined in signal.c. +extern ProtoViewDecoder* Decoders[]; // Defined in signal.c. /* Our view private data. */ #define USER_VALUE_LEN 64 typedef struct { - ProtoViewDecoder *decoder; /* Decoder we are using to create a + ProtoViewDecoder* decoder; /* Decoder we are using to create a message. */ - uint32_t cur_decoder; /* Decoder index when we are yet selecting + uint32_t cur_decoder; /* Decoder index when we are yet selecting a decoder. Used when decoder is NULL. */ - ProtoViewFieldSet *fieldset; /* The fields to populate. */ - uint32_t cur_field; /* Field we are editing right now. This + ProtoViewFieldSet* fieldset; /* The fields to populate. */ + uint32_t cur_field; /* Field we are editing right now. This is the index inside the 'fieldset' fields. */ - char *user_value; /* Keyboard input to replace the current + char* user_value; /* Keyboard input to replace the current field value goes here. */ } BuildViewPrivData; /* Not all the decoders support message bulding, so we can't just * increment / decrement the cur_decoder index here. */ -static void select_next_decoder(ProtoViewApp *app) { - BuildViewPrivData *privdata = app->view_privdata; - do { +static void select_next_decoder(ProtoViewApp* app) { + BuildViewPrivData* privdata = app->view_privdata; + do { privdata->cur_decoder++; - if (Decoders[privdata->cur_decoder] == NULL) - privdata->cur_decoder = 0; + if(Decoders[privdata->cur_decoder] == NULL) privdata->cur_decoder = 0; } while(Decoders[privdata->cur_decoder]->get_fields == NULL); } /* Like select_next_decoder() but goes backward. */ -static void select_prev_decoder(ProtoViewApp *app) { - BuildViewPrivData *privdata = app->view_privdata; +static void select_prev_decoder(ProtoViewApp* app) { + BuildViewPrivData* privdata = app->view_privdata; do { - if (privdata->cur_decoder == 0) { + if(privdata->cur_decoder == 0) { /* Go one after the last one to wrap around. */ while(Decoders[privdata->cur_decoder]) privdata->cur_decoder++; } @@ -45,69 +44,73 @@ static void select_prev_decoder(ProtoViewApp *app) { /* Render the view to select the decoder, among the ones that * support message building. */ -static void render_view_select_decoder(Canvas *const canvas, ProtoViewApp *app) { - BuildViewPrivData *privdata = app->view_privdata; +static void render_view_select_decoder(Canvas* const canvas, ProtoViewApp* app) { + BuildViewPrivData* privdata = app->view_privdata; canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 0, 9, "Signal creator"); canvas_set_font(canvas, FontSecondary); canvas_draw_str(canvas, 0, 19, "up/down: select, ok: choose"); canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas,64,38,AlignCenter,AlignCenter, - Decoders[privdata->cur_decoder]->name); + canvas_draw_str_aligned( + canvas, 64, 38, AlignCenter, AlignCenter, Decoders[privdata->cur_decoder]->name); } /* Render the view that allows the user to populate the fields needed * for the selected decoder to build a message. */ -static void render_view_set_fields(Canvas *const canvas, ProtoViewApp *app) { - BuildViewPrivData *privdata = app->view_privdata; +static void render_view_set_fields(Canvas* const canvas, ProtoViewApp* app) { + BuildViewPrivData* privdata = app->view_privdata; char buf[32]; - snprintf(buf,sizeof(buf), "%s field %d/%d", - privdata->decoder->name, (int)privdata->cur_field+1, + snprintf( + buf, + sizeof(buf), + "%s field %d/%d", + privdata->decoder->name, + (int)privdata->cur_field + 1, (int)privdata->fieldset->numfields); - canvas_set_color(canvas,ColorBlack); - canvas_draw_box(canvas,0,0,128,21); - canvas_set_color(canvas,ColorWhite); + canvas_set_color(canvas, ColorBlack); + canvas_draw_box(canvas, 0, 0, 128, 21); + canvas_set_color(canvas, ColorWhite); canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 1, 9, buf); canvas_set_font(canvas, FontSecondary); canvas_draw_str(canvas, 1, 19, "up/down: next field, ok: edit"); /* Write the field name, type, current content. */ - canvas_set_color(canvas,ColorBlack); - ProtoViewField *field = privdata->fieldset->fields[privdata->cur_field]; - snprintf(buf,sizeof(buf), "%s %s:%d", field->name, - field_get_type_name(field), (int)field->len); + canvas_set_color(canvas, ColorBlack); + ProtoViewField* field = privdata->fieldset->fields[privdata->cur_field]; + snprintf( + buf, sizeof(buf), "%s %s:%d", field->name, field_get_type_name(field), (int)field->len); buf[0] = toupper(buf[0]); canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas,64,30,AlignCenter,AlignCenter,buf); + canvas_draw_str_aligned(canvas, 64, 30, AlignCenter, AlignCenter, buf); canvas_set_font(canvas, FontSecondary); /* Render the current value between "" */ - unsigned int written = (unsigned int) field_to_string(buf+1,sizeof(buf)-1,field); + unsigned int written = (unsigned int)field_to_string(buf + 1, sizeof(buf) - 1, field); buf[0] = '"'; - if (written+3 < sizeof(buf)) memcpy(buf+written+1,"\"\x00",2); - canvas_draw_str_aligned(canvas,63,45,AlignCenter,AlignCenter,buf); + if(written + 3 < sizeof(buf)) memcpy(buf + written + 1, "\"\x00", 2); + canvas_draw_str_aligned(canvas, 63, 45, AlignCenter, AlignCenter, buf); /* Footer instructions. */ canvas_draw_str(canvas, 0, 62, "Long ok: create, < > incr/decr"); } /* Render the build message view. */ -void render_view_build_message(Canvas *const canvas, ProtoViewApp *app) { - BuildViewPrivData *privdata = app->view_privdata; +void render_view_build_message(Canvas* const canvas, ProtoViewApp* app) { + BuildViewPrivData* privdata = app->view_privdata; - if (privdata->decoder) - render_view_set_fields(canvas,app); + if(privdata->decoder) + render_view_set_fields(canvas, app); else - render_view_select_decoder(canvas,app); + render_view_select_decoder(canvas, app); } /* Handle input for the decoder selection. */ -static void process_input_select_decoder(ProtoViewApp *app, InputEvent input) { - BuildViewPrivData *privdata = app->view_privdata; - if (input.type == InputTypeShort) { - if (input.key == InputKeyOk) { +static void process_input_select_decoder(ProtoViewApp* app, InputEvent input) { + BuildViewPrivData* privdata = app->view_privdata; + if(input.type == InputTypeShort) { + if(input.key == InputKeyOk) { privdata->decoder = Decoders[privdata->cur_decoder]; privdata->fieldset = fieldset_new(); privdata->decoder->get_fields(privdata->fieldset); @@ -116,11 +119,8 @@ static void process_input_select_decoder(ProtoViewApp *app, InputEvent input) { * same decoder the user selected, let's populate the * defaults with the current values. So the user will * actaully edit the current message. */ - if (app->signal_decoded && - app->msg_info->decoder == privdata->decoder) - { - fieldset_copy_matching_fields(privdata->fieldset, - app->msg_info->fieldset); + if(app->signal_decoded && app->msg_info->decoder == privdata->decoder) { + fieldset_copy_matching_fields(privdata->fieldset, app->msg_info->fieldset); } /* Now we use the subview system in order to protect the @@ -128,10 +128,10 @@ static void process_input_select_decoder(ProtoViewApp *app, InputEvent input) { Since we are technically into a subview now, we'll have control of < and >. */ InputEvent ii = {.type = InputTypePress, .key = InputKeyDown}; - ui_process_subview_updown(app,ii,2); - } else if (input.key == InputKeyDown) { + ui_process_subview_updown(app, ii, 2); + } else if(input.key == InputKeyDown) { select_next_decoder(app); - } else if (input.key == InputKeyUp) { + } else if(input.key == InputKeyUp) { select_prev_decoder(app); } } @@ -140,12 +140,13 @@ static void process_input_select_decoder(ProtoViewApp *app, InputEvent input) { /* Called after the user typed the new field value in the keyboard. * Let's save it and remove the keyboard view. */ static void text_input_done_callback(void* context) { - ProtoViewApp *app = context; - BuildViewPrivData *privdata = app->view_privdata; + ProtoViewApp* app = context; + BuildViewPrivData* privdata = app->view_privdata; - if (field_set_from_string(privdata->fieldset->fields[privdata->cur_field], - privdata->user_value, strlen(privdata->user_value)) == false) - { + if(field_set_from_string( + privdata->fieldset->fields[privdata->cur_field], + privdata->user_value, + strlen(privdata->user_value)) == false) { ui_show_alert(app, "Invalid value", 1500); } @@ -160,94 +161,88 @@ static void text_input_done_callback(void* context) { * decrement the current field in a much simpler way. * * The current filed is changed by 'incr' amount. */ -static bool increment_current_field(ProtoViewApp *app, int incr) { - BuildViewPrivData *privdata = app->view_privdata; - ProtoViewFieldSet *fs = privdata->fieldset; - ProtoViewField *f = fs->fields[privdata->cur_field]; - return field_incr_value(f,incr); +static bool increment_current_field(ProtoViewApp* app, int incr) { + BuildViewPrivData* privdata = app->view_privdata; + ProtoViewFieldSet* fs = privdata->fieldset; + ProtoViewField* f = fs->fields[privdata->cur_field]; + return field_incr_value(f, incr); } /* Handle input for fields editing mode. */ -static void process_input_set_fields(ProtoViewApp *app, InputEvent input) { - BuildViewPrivData *privdata = app->view_privdata; - ProtoViewFieldSet *fs = privdata->fieldset; +static void process_input_set_fields(ProtoViewApp* app, InputEvent input) { + BuildViewPrivData* privdata = app->view_privdata; + ProtoViewFieldSet* fs = privdata->fieldset; - if (input.type == InputTypeShort && input.key == InputKeyOk) { + if(input.type == InputTypeShort && input.key == InputKeyOk) { /* Show the keyboard to let the user type the new * value. */ - if (privdata->user_value == NULL) - privdata->user_value = malloc(USER_VALUE_LEN); - field_to_string(privdata->user_value, USER_VALUE_LEN, - fs->fields[privdata->cur_field]); - ui_show_keyboard(app, privdata->user_value, USER_VALUE_LEN, - text_input_done_callback); - } else if (input.type == InputTypeShort && input.key == InputKeyDown) { - privdata->cur_field = (privdata->cur_field+1) % fs->numfields; - } else if (input.type == InputTypeShort && input.key == InputKeyUp) { - if (privdata->cur_field == 0) - privdata->cur_field = fs->numfields-1; + if(privdata->user_value == NULL) privdata->user_value = malloc(USER_VALUE_LEN); + field_to_string(privdata->user_value, USER_VALUE_LEN, fs->fields[privdata->cur_field]); + ui_show_keyboard(app, privdata->user_value, USER_VALUE_LEN, text_input_done_callback); + } else if(input.type == InputTypeShort && input.key == InputKeyDown) { + privdata->cur_field = (privdata->cur_field + 1) % fs->numfields; + } else if(input.type == InputTypeShort && input.key == InputKeyUp) { + if(privdata->cur_field == 0) + privdata->cur_field = fs->numfields - 1; else privdata->cur_field--; - } else if (input.type == InputTypeShort && input.key == InputKeyRight) { - increment_current_field(app,1); - } else if (input.type == InputTypeShort && input.key == InputKeyLeft) { - increment_current_field(app,-1); - } else if (input.type == InputTypeRepeat && input.key == InputKeyRight) { + } else if(input.type == InputTypeShort && input.key == InputKeyRight) { + increment_current_field(app, 1); + } else if(input.type == InputTypeShort && input.key == InputKeyLeft) { + increment_current_field(app, -1); + } else if(input.type == InputTypeRepeat && input.key == InputKeyRight) { // The reason why we don't use a large increment directly // is that certain field types only support +1 -1 increments. int times = 10; - while(times--) increment_current_field(app,1); - } else if (input.type == InputTypeRepeat && input.key == InputKeyLeft) { + while(times--) increment_current_field(app, 1); + } else if(input.type == InputTypeRepeat && input.key == InputKeyLeft) { int times = 10; - while(times--) increment_current_field(app,-1); - } else if (input.type == InputTypeLong && input.key == InputKeyOk) { + while(times--) increment_current_field(app, -1); + } else if(input.type == InputTypeLong && input.key == InputKeyOk) { // Build the message in a fresh raw buffer. - if (privdata->decoder->build_message) { - RawSamplesBuffer *rs = raw_samples_alloc(); - privdata->decoder->build_message(rs,privdata->fieldset); + if(privdata->decoder->build_message) { + RawSamplesBuffer* rs = raw_samples_alloc(); + privdata->decoder->build_message(rs, privdata->fieldset); app->signal_decoded = false; // So that the new signal will be - // accepted as the current signal. - scan_for_signal(app,rs); + // accepted as the current signal. + scan_for_signal(app, rs); raw_samples_free(rs); - ui_show_alert(app,"Done: press back key",3000); + ui_show_alert(app, "Done: press back key", 3000); } } } /* Handle input for the build message view. */ -void process_input_build_message(ProtoViewApp *app, InputEvent input) { - BuildViewPrivData *privdata = app->view_privdata; - if (privdata->decoder) - process_input_set_fields(app,input); +void process_input_build_message(ProtoViewApp* app, InputEvent input) { + BuildViewPrivData* privdata = app->view_privdata; + if(privdata->decoder) + process_input_set_fields(app, input); else - process_input_select_decoder(app,input); + process_input_select_decoder(app, input); } /* Enter view callback. */ -void view_enter_build_message(ProtoViewApp *app) { - BuildViewPrivData *privdata = app->view_privdata; +void view_enter_build_message(ProtoViewApp* app) { + BuildViewPrivData* privdata = app->view_privdata; // When we enter the view, the current decoder is just set to zero. // Seek the next valid if needed. - if (Decoders[privdata->cur_decoder]->get_fields == NULL) { + if(Decoders[privdata->cur_decoder]->get_fields == NULL) { select_next_decoder(app); } // However if there is currently a decoded message, and the // decoder of such message supports message building, let's // select it. - if (app->signal_decoded && - app->msg_info->decoder->get_fields && - app->msg_info->decoder->build_message) - { - while(Decoders[privdata->cur_decoder] != app->msg_info->decoder) - select_next_decoder(app); + if(app->signal_decoded && app->msg_info->decoder->get_fields && + app->msg_info->decoder->build_message) { + while(Decoders[privdata->cur_decoder] != app->msg_info->decoder) select_next_decoder(app); } } /* Called on exit for cleanup. */ -void view_exit_build_message(ProtoViewApp *app) { - BuildViewPrivData *privdata = app->view_privdata; - if (privdata->fieldset) fieldset_free(privdata->fieldset); - if (privdata->user_value) free(privdata->user_value); +void view_exit_build_message(ProtoViewApp* app) { + BuildViewPrivData* privdata = app->view_privdata; + if(privdata->fieldset) fieldset_free(privdata->fieldset); + if(privdata->user_value) free(privdata->user_value); } diff --git a/applications/plugins/protoview/view_direct_sampling.c b/applications/plugins/protoview/view_direct_sampling.c index 251a289b8..1ab90f096 100644 --- a/applications/plugins/protoview/view_direct_sampling.c +++ b/applications/plugins/protoview/view_direct_sampling.c @@ -7,47 +7,46 @@ /* Read directly from the G0 CC1101 pin, and draw a black or white * dot depending on the level. */ -void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app) { - if (!app->direct_sampling_enabled) { +void render_view_direct_sampling(Canvas* const canvas, ProtoViewApp* app) { + if(!app->direct_sampling_enabled) { canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas,2,9,"Direct sampling is a special"); - canvas_draw_str(canvas,2,18,"mode that displays the signal"); - canvas_draw_str(canvas,2,27,"captured in real time. Like in"); - canvas_draw_str(canvas,2,36,"a old CRT TV. It's very slow."); - canvas_draw_str(canvas,2,45,"Can crash your Flipper."); + canvas_draw_str(canvas, 2, 9, "Direct sampling is a special"); + canvas_draw_str(canvas, 2, 18, "mode that displays the signal"); + canvas_draw_str(canvas, 2, 27, "captured in real time. Like in"); + canvas_draw_str(canvas, 2, 36, "a old CRT TV. It's very slow."); + canvas_draw_str(canvas, 2, 45, "Can crash your Flipper."); canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas,14,60,"To enable press OK"); + canvas_draw_str(canvas, 14, 60, "To enable press OK"); return; } - for (int y = 0; y < 64; y++) { - for (int x = 0; x < 128; x++) { + for(int y = 0; y < 64; y++) { + for(int x = 0; x < 128; x++) { bool level = furi_hal_gpio_read(&gpio_cc1101_g0); - if (level) canvas_draw_dot(canvas,x,y); + if(level) canvas_draw_dot(canvas, x, y); /* Busy loop: this is a terrible approach as it blocks * everything else, but for now it's the best we can do * to obtain direct data with some spacing. */ - uint32_t x = 250; while(x--); + uint32_t x = 250; + while(x--) + ; } } canvas_set_font(canvas, FontSecondary); - canvas_draw_str_with_border(canvas,36,60,"Direct sampling", - ColorWhite,ColorBlack); + canvas_draw_str_with_border(canvas, 36, 60, "Direct sampling", ColorWhite, ColorBlack); } /* Handle input */ -void process_input_direct_sampling(ProtoViewApp *app, InputEvent input) { - if (input.type == InputTypePress && input.key == InputKeyOk) { +void process_input_direct_sampling(ProtoViewApp* app, InputEvent input) { + if(input.type == InputTypePress && input.key == InputKeyOk) { app->direct_sampling_enabled = !app->direct_sampling_enabled; } } /* Enter view. Stop the subghz thread to prevent access as we read * the CC1101 data directly. */ -void view_enter_direct_sampling(ProtoViewApp *app) { - if (app->txrx->txrx_state == TxRxStateRx && - !app->txrx->debug_timer_sampling) - { +void view_enter_direct_sampling(ProtoViewApp* app) { + if(app->txrx->txrx_state == TxRxStateRx && !app->txrx->debug_timer_sampling) { subghz_worker_stop(app->txrx->worker); } else { raw_sampling_worker_stop(app); @@ -55,10 +54,8 @@ void view_enter_direct_sampling(ProtoViewApp *app) { } /* Exit view. Restore the subghz thread. */ -void view_exit_direct_sampling(ProtoViewApp *app) { - if (app->txrx->txrx_state == TxRxStateRx && - !app->txrx->debug_timer_sampling) - { +void view_exit_direct_sampling(ProtoViewApp* app) { + if(app->txrx->txrx_state == TxRxStateRx && !app->txrx->debug_timer_sampling) { subghz_worker_start(app->txrx->worker); } else { raw_sampling_worker_start(app); diff --git a/applications/plugins/protoview/view_info.c b/applications/plugins/protoview/view_info.c index 6aa69739c..75fc58411 100644 --- a/applications/plugins/protoview/view_info.c +++ b/applications/plugins/protoview/view_info.c @@ -20,31 +20,29 @@ typedef struct { * so that the user can see what they are saving. With left/right * you can move to next rows. Here we store where we are. */ uint32_t signal_display_start_row; - char *filename; + char* filename; uint8_t cur_info_page; // Info page to display. Useful when there are - // too many fields populated by the decoder that - // a single page is not enough. + // too many fields populated by the decoder that + // a single page is not enough. } InfoViewPrivData; /* Draw the text label and value of the specified info field at x,y. */ -static void render_info_field(Canvas *const canvas, - ProtoViewField *f, uint8_t x, uint8_t y) -{ +static void render_info_field(Canvas* const canvas, ProtoViewField* f, uint8_t x, uint8_t y) { char buf[64]; char strval[32]; - field_to_string(strval,sizeof(strval),f); - snprintf(buf,sizeof(buf),"%s: %s", f->name, strval); + field_to_string(strval, sizeof(strval), f); + snprintf(buf, sizeof(buf), "%s: %s", f->name, strval); canvas_set_font(canvas, FontSecondary); canvas_draw_str(canvas, x, y, buf); } /* Render the view with the detected message information. */ #define INFO_LINES_PER_PAGE 5 -static void render_subview_main(Canvas *const canvas, ProtoViewApp *app) { - InfoViewPrivData *privdata = app->view_privdata; - uint8_t pages = (app->msg_info->fieldset->numfields - +(INFO_LINES_PER_PAGE-1)) / INFO_LINES_PER_PAGE; +static void render_subview_main(Canvas* const canvas, ProtoViewApp* app) { + InfoViewPrivData* privdata = app->view_privdata; + uint8_t pages = + (app->msg_info->fieldset->numfields + (INFO_LINES_PER_PAGE - 1)) / INFO_LINES_PER_PAGE; privdata->cur_info_page %= pages; uint8_t current_page = privdata->cur_info_page; char buf[32]; @@ -53,9 +51,9 @@ static void render_subview_main(Canvas *const canvas, ProtoViewApp *app) { canvas_set_font(canvas, FontPrimary); uint8_t y = 8, lineheight = 10; - if (pages > 1) { - snprintf(buf,sizeof(buf),"%s %u/%u", app->msg_info->decoder->name, - current_page+1, pages); + if(pages > 1) { + snprintf( + buf, sizeof(buf), "%s %u/%u", app->msg_info->decoder->name, current_page + 1, pages); canvas_draw_str(canvas, 0, y, buf); } else { canvas_draw_str(canvas, 0, y, app->msg_info->decoder->name); @@ -64,26 +62,30 @@ static void render_subview_main(Canvas *const canvas, ProtoViewApp *app) { /* Draw the info fields. */ uint8_t max_lines = INFO_LINES_PER_PAGE; - uint32_t j = current_page*max_lines; - while (j < app->msg_info->fieldset->numfields) { - render_info_field(canvas,app->msg_info->fieldset->fields[j++],0,y); + uint32_t j = current_page * max_lines; + while(j < app->msg_info->fieldset->numfields) { + render_info_field(canvas, app->msg_info->fieldset->fields[j++], 0, y); y += lineheight; - if (--max_lines == 0) break; + if(--max_lines == 0) break; } /* Draw a vertical "save" label. Temporary solution, to switch to * something better ASAP. */ y = 37; lineheight = 7; - canvas_draw_str(canvas, 119, y, "s"); y += lineheight; - canvas_draw_str(canvas, 119, y, "a"); y += lineheight; - canvas_draw_str(canvas, 119, y, "v"); y += lineheight; - canvas_draw_str(canvas, 119, y, "e"); y += lineheight; + canvas_draw_str(canvas, 119, y, "s"); + y += lineheight; + canvas_draw_str(canvas, 119, y, "a"); + y += lineheight; + canvas_draw_str(canvas, 119, y, "v"); + y += lineheight; + canvas_draw_str(canvas, 119, y, "e"); + y += lineheight; } /* Render view with save option. */ -static void render_subview_save(Canvas *const canvas, ProtoViewApp *app) { - InfoViewPrivData *privdata = app->view_privdata; +static void render_subview_save(Canvas* const canvas, ProtoViewApp* app) { + InfoViewPrivData* privdata = app->view_privdata; /* Display our signal in digital form: here we don't show the * signal with the exact timing of the received samples, but as it @@ -92,21 +94,20 @@ static void render_subview_save(Canvas *const canvas, ProtoViewApp *app) { uint8_t rowheight = 11; uint8_t bitwidth = 4; uint8_t bitheight = 5; - uint32_t idx = privdata->signal_display_start_row * (128/4); + uint32_t idx = privdata->signal_display_start_row * (128 / 4); bool prevbit = false; - for (uint8_t y = bitheight+12; y <= rows*rowheight; y += rowheight) { - for (uint8_t x = 0; x < 128; x += 4) { - bool bit = bitmap_get(app->msg_info->bits, - app->msg_info->bits_bytes,idx); - uint8_t prevy = y + prevbit*(bitheight*-1) - 1; - uint8_t thisy = y + bit*(bitheight*-1) - 1; - canvas_draw_line(canvas,x,prevy,x,thisy); - canvas_draw_line(canvas,x,thisy,x+bitwidth-1,thisy); + for(uint8_t y = bitheight + 12; y <= rows * rowheight; y += rowheight) { + for(uint8_t x = 0; x < 128; x += 4) { + bool bit = bitmap_get(app->msg_info->bits, app->msg_info->bits_bytes, idx); + uint8_t prevy = y + prevbit * (bitheight * -1) - 1; + uint8_t thisy = y + bit * (bitheight * -1) - 1; + canvas_draw_line(canvas, x, prevy, x, thisy); + canvas_draw_line(canvas, x, thisy, x + bitwidth - 1, thisy); prevbit = bit; - if (idx >= app->msg_info->pulses_count) { + if(idx >= app->msg_info->pulses_count) { canvas_set_color(canvas, ColorWhite); - canvas_draw_dot(canvas, x+1,thisy); - canvas_draw_dot(canvas, x+3,thisy); + canvas_draw_dot(canvas, x + 1, thisy); + canvas_draw_dot(canvas, x + 3, thisy); canvas_set_color(canvas, ColorBlack); } idx++; // Draw next bit @@ -118,28 +119,32 @@ static void render_subview_save(Canvas *const canvas, ProtoViewApp *app) { } /* Render the selected subview of this view. */ -void render_view_info(Canvas *const canvas, ProtoViewApp *app) { - if (app->signal_decoded == false) { +void render_view_info(Canvas* const canvas, ProtoViewApp* app) { + if(app->signal_decoded == false) { canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 30,36,"No signal decoded"); + canvas_draw_str(canvas, 30, 36, "No signal decoded"); return; } - ui_show_available_subviews(canvas,app,SubViewInfoLast); + ui_show_available_subviews(canvas, app, SubViewInfoLast); switch(app->current_subview[app->current_view]) { - case SubViewInfoMain: render_subview_main(canvas,app); break; - case SubViewInfoSave: render_subview_save(canvas,app); break; + case SubViewInfoMain: + render_subview_main(canvas, app); + break; + case SubViewInfoSave: + render_subview_save(canvas, app); + break; } } /* The user typed the file name. Let's save it and remove the keyboard * view. */ static void text_input_done_callback(void* context) { - ProtoViewApp *app = context; - InfoViewPrivData *privdata = app->view_privdata; + ProtoViewApp* app = context; + InfoViewPrivData* privdata = app->view_privdata; - FuriString *save_path = furi_string_alloc_printf( - "%s/%s.sub", EXT_PATH("subghz"), privdata->filename); + FuriString* save_path = + furi_string_alloc_printf("%s/%s.sub", EXT_PATH("subghz"), privdata->filename); save_signal(app, furi_string_get_cstr(save_path)); furi_string_free(save_path); @@ -151,22 +156,22 @@ static void text_input_done_callback(void* context) { /* Replace all the occurrences of character c1 with c2 in the specified * string. */ -void str_replace(char *buf, char c1, char c2) { - char *p = buf; +void str_replace(char* buf, char c1, char c2) { + char* p = buf; while(*p) { - if (*p == c1) *p = c2; + if(*p == c1) *p = c2; p++; } } /* Set a random filename the user can edit. */ -void set_signal_random_filename(ProtoViewApp *app, char *buf, size_t buflen) { +void set_signal_random_filename(ProtoViewApp* app, char* buf, size_t buflen) { char suffix[6]; - set_random_name(suffix,sizeof(suffix)); - snprintf(buf,buflen,"%.10s-%s-%d",app->msg_info->decoder->name,suffix,rand()%1000); - str_replace(buf,' ','_'); - str_replace(buf,'-','_'); - str_replace(buf,'/','_'); + set_random_name(suffix, sizeof(suffix)); + snprintf(buf, buflen, "%.10s-%s-%d", app->msg_info->decoder->name, suffix, rand() % 1000); + str_replace(buf, ' ', '_'); + str_replace(buf, '-', '_'); + str_replace(buf, '/', '_'); } /* ========================== Signal transmission =========================== */ @@ -180,20 +185,20 @@ typedef enum { SendSignalEndTransmission } SendSignalState; -#define PROTOVIEW_SENDSIGNAL_START_GAP 10000 /* microseconds. */ -#define PROTOVIEW_SENDSIGNAL_END_GAP 10000 /* microseconds. */ +#define PROTOVIEW_SENDSIGNAL_START_GAP 10000 /* microseconds. */ +#define PROTOVIEW_SENDSIGNAL_END_GAP 10000 /* microseconds. */ typedef struct { - SendSignalState state; // Current state. - uint32_t curpos; // Current bit position of data to send. - ProtoViewApp *app; // App reference. + SendSignalState state; // Current state. + uint32_t curpos; // Current bit position of data to send. + ProtoViewApp* app; // App reference. uint32_t start_gap_dur; // Gap to send at the start. - uint32_t end_gap_dur; // Gap to send at the end. + uint32_t end_gap_dur; // Gap to send at the end. } SendSignalCtx; /* Setup the state context for the callback responsible to feed data * to the subghz async tx system. */ -static void send_signal_init(SendSignalCtx *ss, ProtoViewApp *app) { +static void send_signal_init(SendSignalCtx* ss, ProtoViewApp* app) { ss->state = SendSignalSendStartGap; ss->curpos = 0; ss->app = app; @@ -214,27 +219,26 @@ static void send_signal_init(SendSignalCtx *ss, ProtoViewApp *app) { * message we are, in ss->curoff. We also send a start and end gap in order * to make sure the transmission is clear. */ -LevelDuration radio_tx_feed_data(void *ctx) { - SendSignalCtx *ss = ctx; +LevelDuration radio_tx_feed_data(void* ctx) { + SendSignalCtx* ss = ctx; /* Send start gap. */ - if (ss->state == SendSignalSendStartGap) { + if(ss->state == SendSignalSendStartGap) { ss->state = SendSignalSendBits; - return level_duration_make(0,ss->start_gap_dur); + return level_duration_make(0, ss->start_gap_dur); } /* Send data. */ - if (ss->state == SendSignalSendBits) { + if(ss->state == SendSignalSendBits) { uint32_t dur = 0, j; uint32_t level = 0; /* Let's see how many consecutive bits we have with the same * level. */ - for (j = 0; ss->curpos+j < ss->app->msg_info->pulses_count; j++) { - uint32_t l = bitmap_get(ss->app->msg_info->bits, - ss->app->msg_info->bits_bytes, - ss->curpos+j); - if (j == 0) { + for(j = 0; ss->curpos + j < ss->app->msg_info->pulses_count; j++) { + uint32_t l = + bitmap_get(ss->app->msg_info->bits, ss->app->msg_info->bits_bytes, ss->curpos + j); + if(j == 0) { /* At the first bit of this sequence, we store the * level of the sequence. */ level = l; @@ -244,22 +248,21 @@ LevelDuration radio_tx_feed_data(void *ctx) { /* As long as the level is the same, we update the duration. * Otherwise stop the loop and return this sample. */ - if (l != level) break; + if(l != level) break; dur += ss->app->msg_info->short_pulse_dur; } ss->curpos += j; /* If this was the last set of bits, change the state to * send the final gap. */ - if (ss->curpos >= ss->app->msg_info->pulses_count) - ss->state = SendSignalSendEndGap; + if(ss->curpos >= ss->app->msg_info->pulses_count) ss->state = SendSignalSendEndGap; return level_duration_make(level, dur); } /* Send end gap. */ - if (ss->state == SendSignalSendEndGap) { + if(ss->state == SendSignalSendEndGap) { ss->state = SendSignalEndTransmission; - return level_duration_make(0,ss->end_gap_dur); + return level_duration_make(0, ss->end_gap_dur); } /* End transmission. Here state is guaranteed @@ -268,7 +271,7 @@ LevelDuration radio_tx_feed_data(void *ctx) { } /* Vibrate and produce a click sound when a signal is sent. */ -void notify_signal_sent(ProtoViewApp *app) { +void notify_signal_sent(ProtoViewApp* app) { static const NotificationSequence sent_seq = { &message_blue_255, &message_vibro_on, @@ -277,59 +280,53 @@ void notify_signal_sent(ProtoViewApp *app) { &message_sound_off, &message_vibro_off, &message_blue_0, - NULL - }; + NULL}; notification_message(app->notification, &sent_seq); } /* Handle input for the info view. */ -void process_input_info(ProtoViewApp *app, InputEvent input) { +void process_input_info(ProtoViewApp* app, InputEvent input) { /* If we don't have a decoded signal, we don't allow to go up/down * in the subviews: they are only useful when a loaded signal. */ - if (app->signal_decoded && - ui_process_subview_updown(app,input,SubViewInfoLast)) return; + if(app->signal_decoded && ui_process_subview_updown(app, input, SubViewInfoLast)) return; - InfoViewPrivData *privdata = app->view_privdata; + InfoViewPrivData* privdata = app->view_privdata; int subview = ui_get_current_subview(app); /* Main subview. */ - if (subview == SubViewInfoMain) { - if (input.type == InputTypeLong && input.key == InputKeyOk) { + if(subview == SubViewInfoMain) { + if(input.type == InputTypeLong && input.key == InputKeyOk) { /* Reset the current sample to capture the next. */ reset_current_signal(app); - } else if (input.type == InputTypeShort && input.key == InputKeyOk) { + } else if(input.type == InputTypeShort && input.key == InputKeyOk) { /* Show next info page. */ privdata->cur_info_page++; } - } else if (subview == SubViewInfoSave) { - /* Save subview. */ - if (input.type == InputTypePress && input.key == InputKeyRight) { + } else if(subview == SubViewInfoSave) { + /* Save subview. */ + if(input.type == InputTypePress && input.key == InputKeyRight) { privdata->signal_display_start_row++; - } else if (input.type == InputTypePress && input.key == InputKeyLeft) { - if (privdata->signal_display_start_row != 0) - privdata->signal_display_start_row--; - } else if (input.type == InputTypeLong && input.key == InputKeyOk) - { + } else if(input.type == InputTypePress && input.key == InputKeyLeft) { + if(privdata->signal_display_start_row != 0) privdata->signal_display_start_row--; + } else if(input.type == InputTypeLong && input.key == InputKeyOk) { // We have have the buffer already allocated, in case the // user aborted with BACK a previous saving. - if (privdata->filename == NULL) - privdata->filename = malloc(SAVE_FILENAME_LEN); - set_signal_random_filename(app,privdata->filename,SAVE_FILENAME_LEN); - ui_show_keyboard(app, privdata->filename, SAVE_FILENAME_LEN, - text_input_done_callback); - } else if (input.type == InputTypeShort && input.key == InputKeyOk) { + if(privdata->filename == NULL) privdata->filename = malloc(SAVE_FILENAME_LEN); + set_signal_random_filename(app, privdata->filename, SAVE_FILENAME_LEN); + ui_show_keyboard(app, privdata->filename, SAVE_FILENAME_LEN, text_input_done_callback); + } else if(input.type == InputTypeShort && input.key == InputKeyOk) { SendSignalCtx send_state; - send_signal_init(&send_state,app); - radio_tx_signal(app,radio_tx_feed_data,&send_state); + send_signal_init(&send_state, app); + radio_tx_signal(app, radio_tx_feed_data, &send_state); notify_signal_sent(app); } } } /* Called on view exit. */ -void view_exit_info(ProtoViewApp *app) { - InfoViewPrivData *privdata = app->view_privdata; +void view_exit_info(ProtoViewApp* app) { + InfoViewPrivData* privdata = app->view_privdata; // When the user aborts the keyboard input, we are left with the // filename buffer allocated. - if (privdata->filename) free(privdata->filename); + if(privdata->filename) free(privdata->filename); } diff --git a/applications/plugins/protoview/view_raw_signal.c b/applications/plugins/protoview/view_raw_signal.c index 023e986f9..38354bef9 100644 --- a/applications/plugins/protoview/view_raw_signal.c +++ b/applications/plugins/protoview/view_raw_signal.c @@ -12,7 +12,7 @@ * * The 'idx' argument is the first sample to render in the circular * buffer. */ -void render_signal(ProtoViewApp *app, Canvas *const canvas, RawSamplesBuffer *buf, uint32_t idx) { +void render_signal(ProtoViewApp* app, Canvas* const canvas, RawSamplesBuffer* buf, uint32_t idx) { canvas_set_color(canvas, ColorBlack); int rows = 8; @@ -20,31 +20,29 @@ void render_signal(ProtoViewApp *app, Canvas *const canvas, RawSamplesBuffer *bu uint32_t start_idx = idx; bool level = 0; uint32_t dur = 0, sample_num = 0; - for (int row = 0; row < rows ; row++) { - for (int x = 0; x < 128; x++) { - int y = 3 + row*8; - if (dur < time_per_pixel/2) { + for(int row = 0; row < rows; row++) { + for(int x = 0; x < 128; x++) { + int y = 3 + row * 8; + if(dur < time_per_pixel / 2) { /* Get more data. */ raw_samples_get(buf, idx++, &level, &dur); sample_num++; } - canvas_draw_line(canvas, x,y,x,y-(level*3)); + canvas_draw_line(canvas, x, y, x, y - (level * 3)); /* Write a small triangle under the last sample detected. */ - if (app->signal_bestlen != 0 && - sample_num+start_idx == app->signal_bestlen+1) - { - canvas_draw_dot(canvas,x,y+2); - canvas_draw_dot(canvas,x-1,y+3); - canvas_draw_dot(canvas,x,y+3); - canvas_draw_dot(canvas,x+1,y+3); + if(app->signal_bestlen != 0 && sample_num + start_idx == app->signal_bestlen + 1) { + canvas_draw_dot(canvas, x, y + 2); + canvas_draw_dot(canvas, x - 1, y + 3); + canvas_draw_dot(canvas, x, y + 3); + canvas_draw_dot(canvas, x + 1, y + 3); sample_num++; /* Make sure we don't mark the next, too. */ } /* Remove from the current level duration the time we * just plot. */ - if (dur > time_per_pixel) + if(dur > time_per_pixel) dur -= time_per_pixel; else dur = 0; @@ -53,61 +51,63 @@ void render_signal(ProtoViewApp *app, Canvas *const canvas, RawSamplesBuffer *bu } /* Raw pulses rendering. This is our default view. */ -void render_view_raw_pulses(Canvas *const canvas, ProtoViewApp *app) { +void render_view_raw_pulses(Canvas* const canvas, ProtoViewApp* app) { /* Show signal. */ render_signal(app, canvas, DetectedSamples, app->signal_offset); /* Show signal information. */ char buf[64]; - snprintf(buf,sizeof(buf),"%luus", - (unsigned long)DetectedSamples->short_pulse_dur); + snprintf(buf, sizeof(buf), "%luus", (unsigned long)DetectedSamples->short_pulse_dur); canvas_set_font(canvas, FontSecondary); canvas_draw_str_with_border(canvas, 97, 63, buf, ColorWhite, ColorBlack); - if (app->signal_decoded) { + if(app->signal_decoded) { canvas_set_font(canvas, FontPrimary); - canvas_draw_str_with_border(canvas, 1, 61, app->msg_info->decoder->name, ColorWhite, ColorBlack); + canvas_draw_str_with_border( + canvas, 1, 61, app->msg_info->decoder->name, ColorWhite, ColorBlack); } } /* Handle input for the raw pulses view. */ -void process_input_raw_pulses(ProtoViewApp *app, InputEvent input) { - if (input.type == InputTypeRepeat) { +void process_input_raw_pulses(ProtoViewApp* app, InputEvent input) { + if(input.type == InputTypeRepeat) { /* Handle panning of the signal window. Long pressing * right will show successive samples, long pressing left * previous samples. */ - if (input.key == InputKeyRight) app->signal_offset++; - else if (input.key == InputKeyLeft) app->signal_offset--; - } else if (input.type == InputTypeLong) { - if (input.key == InputKeyOk) { + if(input.key == InputKeyRight) + app->signal_offset++; + else if(input.key == InputKeyLeft) + app->signal_offset--; + } else if(input.type == InputTypeLong) { + if(input.key == InputKeyOk) { /* Reset the current sample to capture the next. */ reset_current_signal(app); } - } else if (input.type == InputTypeShort) { - if (input.key == InputKeyOk) { + } else if(input.type == InputTypeShort) { + if(input.key == InputKeyOk) { app->signal_offset = 0; - adjust_raw_view_scale(app,DetectedSamples->short_pulse_dur); - } else if (input.key == InputKeyDown) { + adjust_raw_view_scale(app, DetectedSamples->short_pulse_dur); + } else if(input.key == InputKeyDown) { /* Rescaling. The set becomes finer under 50us per pixel. */ uint32_t scale_step = app->us_scale >= 50 ? 50 : 10; - if (app->us_scale < 500) app->us_scale += scale_step; - } else if (input.key == InputKeyUp) { + if(app->us_scale < 500) app->us_scale += scale_step; + } else if(input.key == InputKeyUp) { uint32_t scale_step = app->us_scale > 50 ? 50 : 10; - if (app->us_scale > 10) app->us_scale -= scale_step; + if(app->us_scale > 10) app->us_scale -= scale_step; } } } /* Adjust raw view scale depending on short pulse duration. */ -void adjust_raw_view_scale(ProtoViewApp *app, uint32_t short_pulse_dur) { - if (short_pulse_dur == 0) +void adjust_raw_view_scale(ProtoViewApp* app, uint32_t short_pulse_dur) { + if(short_pulse_dur == 0) app->us_scale = PROTOVIEW_RAW_VIEW_DEFAULT_SCALE; - else if (short_pulse_dur < 75) + else if(short_pulse_dur < 75) app->us_scale = 10; - else if (short_pulse_dur < 145) + else if(short_pulse_dur < 145) app->us_scale = 30; - else if (short_pulse_dur < 400) + else if(short_pulse_dur < 400) app->us_scale = 100; - else if (short_pulse_dur < 1000) + else if(short_pulse_dur < 1000) app->us_scale = 200; else app->us_scale = PROTOVIEW_RAW_VIEW_DEFAULT_SCALE; diff --git a/applications/plugins/protoview/view_settings.c b/applications/plugins/protoview/view_settings.c index 1e2dce226..09abf5a2a 100644 --- a/applications/plugins/protoview/view_settings.c +++ b/applications/plugins/protoview/view_settings.c @@ -6,30 +6,30 @@ /* Renders a single view with frequency and modulation setting. However * this are logically two different views, and only one of the settings * will be highlighted. */ -void render_view_settings(Canvas *const canvas, ProtoViewApp *app) { +void render_view_settings(Canvas* const canvas, ProtoViewApp* app) { canvas_set_font(canvas, FontPrimary); - if (app->current_view == ViewFrequencySettings) - canvas_draw_str_with_border(canvas,1,10,"Frequency",ColorWhite,ColorBlack); + if(app->current_view == ViewFrequencySettings) + canvas_draw_str_with_border(canvas, 1, 10, "Frequency", ColorWhite, ColorBlack); else - canvas_draw_str(canvas,1,10,"Frequency"); + canvas_draw_str(canvas, 1, 10, "Frequency"); - if (app->current_view == ViewModulationSettings) - canvas_draw_str_with_border(canvas,70,10,"Modulation",ColorWhite,ColorBlack); + if(app->current_view == ViewModulationSettings) + canvas_draw_str_with_border(canvas, 70, 10, "Modulation", ColorWhite, ColorBlack); else - canvas_draw_str(canvas,70,10,"Modulation"); + canvas_draw_str(canvas, 70, 10, "Modulation"); canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas,10,61,"Use up and down to modify"); + canvas_draw_str(canvas, 10, 61, "Use up and down to modify"); - if (app->txrx->debug_timer_sampling) - canvas_draw_str(canvas,3,52,"(DEBUG timer sampling is ON)"); + if(app->txrx->debug_timer_sampling) + canvas_draw_str(canvas, 3, 52, "(DEBUG timer sampling is ON)"); /* Show frequency. We can use big numbers font since it's just a number. */ - if (app->current_view == ViewFrequencySettings) { + if(app->current_view == ViewFrequencySettings) { char buf[16]; - snprintf(buf,sizeof(buf),"%.2f",(double)app->frequency/1000000); + snprintf(buf, sizeof(buf), "%.2f", (double)app->frequency / 1000000); canvas_set_font(canvas, FontBigNumbers); canvas_draw_str(canvas, 30, 40, buf); - } else if (app->current_view == ViewModulationSettings) { + } else if(app->current_view == ViewModulationSettings) { int current = app->modulation; canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 33, 39, ProtoViewModulations[current].name); @@ -37,13 +37,13 @@ void render_view_settings(Canvas *const canvas, ProtoViewApp *app) { } /* Handle input for the settings view. */ -void process_input_settings(ProtoViewApp *app, InputEvent input) { - if (input.type == InputTypeLong && input.key == InputKeyOk) { +void process_input_settings(ProtoViewApp* app, InputEvent input) { + if(input.type == InputTypeLong && input.key == InputKeyOk) { /* Long pressing to OK sets the default frequency and * modulation. */ app->frequency = subghz_setting_get_default_frequency(app->setting); app->modulation = 0; - } else if (0 && input.type == InputTypeLong && input.key == InputKeyDown) { + } else if(0 && input.type == InputTypeLong && input.key == InputKeyDown) { /* Long pressing to down switches between normal and debug * timer sampling mode. NOTE: this feature is disabled for users, * only useful for devs (if useful at all). */ @@ -55,42 +55,40 @@ void process_input_settings(ProtoViewApp *app, InputEvent input) { app->txrx->debug_timer_sampling = !app->txrx->debug_timer_sampling; radio_begin(app); radio_rx(app); - } else if (input.type == InputTypePress && - (input.key != InputKeyDown || input.key != InputKeyUp)) - { + } else if(input.type == InputTypePress && (input.key != InputKeyDown || input.key != InputKeyUp)) { /* Handle up and down to change frequency or modulation. */ - if (app->current_view == ViewFrequencySettings) { + if(app->current_view == ViewFrequencySettings) { size_t curidx = 0, i; size_t count = subghz_setting_get_frequency_count(app->setting); /* Scan the list of frequencies to check for the index of the * currently set frequency. */ for(i = 0; i < count; i++) { - uint32_t freq = subghz_setting_get_frequency(app->setting,i); - if (freq == app->frequency) { + uint32_t freq = subghz_setting_get_frequency(app->setting, i); + if(freq == app->frequency) { curidx = i; break; } } - if (i == count) return; /* Should never happen. */ + if(i == count) return; /* Should never happen. */ - if (input.key == InputKeyUp) { - curidx = curidx == 0 ? count-1 : curidx-1; - } else if (input.key == InputKeyDown) { - curidx = (curidx+1) % count; + if(input.key == InputKeyUp) { + curidx = curidx == 0 ? count - 1 : curidx - 1; + } else if(input.key == InputKeyDown) { + curidx = (curidx + 1) % count; } else { return; } - app->frequency = subghz_setting_get_frequency(app->setting,curidx); - } else if (app->current_view == ViewModulationSettings) { + app->frequency = subghz_setting_get_frequency(app->setting, curidx); + } else if(app->current_view == ViewModulationSettings) { uint32_t count = 0; uint32_t modid = app->modulation; while(ProtoViewModulations[count].name != NULL) count++; - if (input.key == InputKeyUp) { - modid = modid == 0 ? count-1 : modid-1; - } else if (input.key == InputKeyDown) { - modid = (modid+1) % count; + if(input.key == InputKeyUp) { + modid = modid == 0 ? count - 1 : modid - 1; + } else if(input.key == InputKeyDown) { + modid = (modid + 1) % count; } else { return; } @@ -106,9 +104,13 @@ void process_input_settings(ProtoViewApp *app, InputEvent input) { /* When the user switches to some other view, if they changed the parameters * we need to restart the radio with the right frequency and modulation. */ -void view_exit_settings(ProtoViewApp *app) { - if (app->txrx->freq_mod_changed) { - FURI_LOG_E(TAG, "Setting view, setting frequency/modulation to %lu %s", app->frequency, ProtoViewModulations[app->modulation].name); +void view_exit_settings(ProtoViewApp* app) { + if(app->txrx->freq_mod_changed) { + FURI_LOG_E( + TAG, + "Setting view, setting frequency/modulation to %lu %s", + app->frequency, + ProtoViewModulations[app->modulation].name); radio_rx_end(app); radio_begin(app); radio_rx(app); diff --git a/applications/plugins/tama_p1/hal.c b/applications/plugins/tama_p1/hal.c index 211457803..585cd88c4 100644 --- a/applications/plugins/tama_p1/hal.c +++ b/applications/plugins/tama_p1/hal.c @@ -40,7 +40,7 @@ static void tama_p1_hal_log(log_level_t level, char* buff, ...) { va_list args; va_start(args, buff); furi_string_cat_vprintf(string, buff, args); - va_end(args); + va_end(args); switch(level) { case LOG_ERROR: diff --git a/applications/plugins/tama_p1/tama.h b/applications/plugins/tama_p1/tama.h index e2a267443..e8eecc945 100644 --- a/applications/plugins/tama_p1/tama.h +++ b/applications/plugins/tama_p1/tama.h @@ -13,7 +13,6 @@ #define STATE_FILE_VERSION 2 #define TAMA_SAVE_PATH EXT_PATH("tama_p1/save.bin") - typedef struct { FuriThread* thread; hal_t hal; diff --git a/applications/plugins/tama_p1/tama_p1.c b/applications/plugins/tama_p1/tama_p1.c index 7184638d7..0e7686a06 100644 --- a/applications/plugins/tama_p1/tama_p1.c +++ b/applications/plugins/tama_p1/tama_p1.c @@ -52,7 +52,6 @@ static void tama_p1_draw_callback(Canvas* const canvas, void* cb_ctx) { uint16_t lcd_icon_lower_left = lcd_matrix_left; uint16_t lcd_icon_spacing_horiz = (lcd_matrix_scaled_width - (4 * TAMA_LCD_ICON_SIZE)) / 3 + TAMA_LCD_ICON_SIZE; - uint16_t y = lcd_matrix_top; for(uint8_t row = 0; row < 16; ++row) { @@ -71,7 +70,7 @@ static void tama_p1_draw_callback(Canvas* const canvas, void* cb_ctx) { // Start drawing icons uint8_t lcd_icons = g_ctx->icons; - + // Draw top icons y = lcd_icon_upper_top; // y = 64 - TAMA_LCD_ICON_SIZE; @@ -114,135 +113,134 @@ static void tama_p1_update_timer_callback(FuriMessageQueue* event_queue) { TamaEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, 0); } - -static void tama_p1_load_state() { - state_t *state; + +static void tama_p1_load_state() { + state_t* state; uint8_t buf[4]; - bool error = false; + bool error = false; state = tamalib_get_state(); - Storage* storage = furi_record_open(RECORD_STORAGE); - File* file = storage_file_alloc(storage); - if(storage_file_open(file, TAMA_SAVE_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { - - storage_file_read(file, &buf, 4); - if (buf[0] != (uint8_t) STATE_FILE_MAGIC[0] || buf[1] != (uint8_t) STATE_FILE_MAGIC[1] || - buf[2] != (uint8_t) STATE_FILE_MAGIC[2] || buf[3] != (uint8_t) STATE_FILE_MAGIC[3]) { + Storage* storage = furi_record_open(RECORD_STORAGE); + File* file = storage_file_alloc(storage); + if(storage_file_open(file, TAMA_SAVE_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { + storage_file_read(file, &buf, 4); + if(buf[0] != (uint8_t)STATE_FILE_MAGIC[0] || buf[1] != (uint8_t)STATE_FILE_MAGIC[1] || + buf[2] != (uint8_t)STATE_FILE_MAGIC[2] || buf[3] != (uint8_t)STATE_FILE_MAGIC[3]) { FURI_LOG_E(TAG, "FATAL: Wrong state file magic in \"%s\" !\n", TAMA_SAVE_PATH); error = true; } - storage_file_read(file, &buf, 1); - if (buf[0] != STATE_FILE_VERSION) { + storage_file_read(file, &buf, 1); + if(buf[0] != STATE_FILE_VERSION) { FURI_LOG_E(TAG, "FATAL: Unsupported version"); error = true; } - if (!error) { + if(!error) { FURI_LOG_D(TAG, "Reading save.bin"); - storage_file_read(file, &buf, 2); - *(state->pc) = buf[0] | ((buf[1] & 0x1F) << 8); - - storage_file_read(file, &buf, 2); - *(state->x) = buf[0] | ((buf[1] & 0xF) << 8); + storage_file_read(file, &buf, 2); + *(state->pc) = buf[0] | ((buf[1] & 0x1F) << 8); - storage_file_read(file, &buf, 2); - *(state->y) = buf[0] | ((buf[1] & 0xF) << 8); + storage_file_read(file, &buf, 2); + *(state->x) = buf[0] | ((buf[1] & 0xF) << 8); - storage_file_read(file, &buf, 1); - *(state->a) = buf[0] & 0xF; + storage_file_read(file, &buf, 2); + *(state->y) = buf[0] | ((buf[1] & 0xF) << 8); - storage_file_read(file, &buf, 1); - *(state->b) = buf[0] & 0xF; + storage_file_read(file, &buf, 1); + *(state->a) = buf[0] & 0xF; - storage_file_read(file, &buf, 1); + storage_file_read(file, &buf, 1); + *(state->b) = buf[0] & 0xF; + + storage_file_read(file, &buf, 1); *(state->np) = buf[0] & 0x1F; - storage_file_read(file, &buf, 1); + storage_file_read(file, &buf, 1); *(state->sp) = buf[0]; - storage_file_read(file, &buf, 1); + storage_file_read(file, &buf, 1); *(state->flags) = buf[0] & 0xF; - storage_file_read(file, &buf, 4); + storage_file_read(file, &buf, 4); *(state->tick_counter) = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); - storage_file_read(file, &buf, 4); - *(state->clk_timer_timestamp) = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); + storage_file_read(file, &buf, 4); + *(state->clk_timer_timestamp) = buf[0] | (buf[1] << 8) | (buf[2] << 16) | + (buf[3] << 24); - storage_file_read(file, &buf, 4); - *(state->prog_timer_timestamp) = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); + storage_file_read(file, &buf, 4); + *(state->prog_timer_timestamp) = buf[0] | (buf[1] << 8) | (buf[2] << 16) | + (buf[3] << 24); - storage_file_read(file, &buf, 1); + storage_file_read(file, &buf, 1); *(state->prog_timer_enabled) = buf[0] & 0x1; - storage_file_read(file, &buf, 1); + storage_file_read(file, &buf, 1); *(state->prog_timer_data) = buf[0]; - storage_file_read(file, &buf, 1); + storage_file_read(file, &buf, 1); *(state->prog_timer_rld) = buf[0]; - storage_file_read(file, &buf, 4); + storage_file_read(file, &buf, 4); *(state->call_depth) = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); FURI_LOG_D(TAG, "Restoring Interupts"); - for (uint32_t i = 0; i < INT_SLOT_NUM; i++) { - storage_file_read(file, &buf, 1); + for(uint32_t i = 0; i < INT_SLOT_NUM; i++) { + storage_file_read(file, &buf, 1); state->interrupts[i].factor_flag_reg = buf[0] & 0xF; - storage_file_read(file, &buf, 1); + storage_file_read(file, &buf, 1); state->interrupts[i].mask_reg = buf[0] & 0xF; - storage_file_read(file, &buf, 1); + storage_file_read(file, &buf, 1); state->interrupts[i].triggered = buf[0] & 0x1; } /* First 640 half bytes correspond to the RAM */ FURI_LOG_D(TAG, "Restoring RAM"); - for (uint32_t i = 0; i < MEM_RAM_SIZE; i++) { - storage_file_read(file, &buf, 1); + for(uint32_t i = 0; i < MEM_RAM_SIZE; i++) { + storage_file_read(file, &buf, 1); SET_RAM_MEMORY(state->memory, i + MEM_RAM_ADDR, buf[0] & 0xF); } /* I/Os are from 0xF00 to 0xF7F */ FURI_LOG_D(TAG, "Restoring I/O"); - for (uint32_t i = 0; i < MEM_IO_SIZE; i++) { - storage_file_read(file, &buf, 1); + for(uint32_t i = 0; i < MEM_IO_SIZE; i++) { + storage_file_read(file, &buf, 1); SET_IO_MEMORY(state->memory, i + MEM_IO_ADDR, buf[0] & 0xF); - } - FURI_LOG_D(TAG, "Refreshing Hardware"); - tamalib_refresh_hw(); - } + } + FURI_LOG_D(TAG, "Refreshing Hardware"); + tamalib_refresh_hw(); + } } - + storage_file_close(file); storage_file_free(file); - furi_record_close(RECORD_STORAGE); + furi_record_close(RECORD_STORAGE); } - static void tama_p1_save_state() { - // Saving state FURI_LOG_D(TAG, "Saving Gamestate"); uint8_t buf[4]; - state_t *state; + state_t* state; uint32_t offset = 0; state = tamalib_get_state(); - - Storage* storage = furi_record_open(RECORD_STORAGE); - File* file = storage_file_alloc(storage); + + Storage* storage = furi_record_open(RECORD_STORAGE); + File* file = storage_file_alloc(storage); if(storage_file_open(file, TAMA_SAVE_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { - buf[0] = (uint8_t) STATE_FILE_MAGIC[0]; - buf[1] = (uint8_t) STATE_FILE_MAGIC[1]; - buf[2] = (uint8_t) STATE_FILE_MAGIC[2]; - buf[3] = (uint8_t) STATE_FILE_MAGIC[3]; + buf[0] = (uint8_t)STATE_FILE_MAGIC[0]; + buf[1] = (uint8_t)STATE_FILE_MAGIC[1]; + buf[2] = (uint8_t)STATE_FILE_MAGIC[2]; + buf[3] = (uint8_t)STATE_FILE_MAGIC[3]; offset += storage_file_write(file, &buf, sizeof(buf)); - + buf[0] = STATE_FILE_VERSION & 0xFF; offset += storage_file_write(file, &buf, 1); - + buf[0] = *(state->pc) & 0xFF; buf[1] = (*(state->pc) >> 8) & 0x1F; offset += storage_file_write(file, &buf, 2); @@ -303,7 +301,7 @@ static void tama_p1_save_state() { buf[3] = (*(state->call_depth) >> 24) & 0xFF; offset += storage_file_write(file, &buf, sizeof(buf)); - for (uint32_t i = 0; i < INT_SLOT_NUM; i++) { + for(uint32_t i = 0; i < INT_SLOT_NUM; i++) { buf[0] = state->interrupts[i].factor_flag_reg & 0xF; offset += storage_file_write(file, &buf, 1); @@ -315,17 +313,17 @@ static void tama_p1_save_state() { } /* First 640 half bytes correspond to the RAM */ - for (uint32_t i = 0; i < MEM_RAM_SIZE; i++) { + for(uint32_t i = 0; i < MEM_RAM_SIZE; i++) { buf[0] = GET_RAM_MEMORY(state->memory, i + MEM_RAM_ADDR) & 0xF; offset += storage_file_write(file, &buf, 1); } /* I/Os are from 0xF00 to 0xF7F */ - for (uint32_t i = 0; i < MEM_IO_SIZE; i++) { + for(uint32_t i = 0; i < MEM_IO_SIZE; i++) { buf[0] = GET_IO_MEMORY(state->memory, i + MEM_IO_ADDR) & 0xF; offset += storage_file_write(file, &buf, 1); } - } + } storage_file_close(file); storage_file_free(file); furi_record_close(RECORD_STORAGE); @@ -333,7 +331,6 @@ static void tama_p1_save_state() { FURI_LOG_D(TAG, "Finished Writing %lu", offset); } - static int32_t tama_p1_worker(void* context) { bool running = true; FuriMutex* mutex = context; @@ -357,8 +354,6 @@ static int32_t tama_p1_worker(void* context) { furi_mutex_release(mutex); return 0; } - - static void tama_p1_init(TamaApp* const ctx) { g_ctx = ctx; @@ -485,9 +480,9 @@ int32_t tama_p1_app(void* p) { tamalib_set_button(BTN_MIDDLE, tama_btn_state); } else if(event.input.key == InputKeyRight) { tamalib_set_button(BTN_RIGHT, tama_btn_state); - } else if(event.input.key == InputKeyDown && event.input.type == InputTypeShort) { + } else if(event.input.key == InputKeyDown && event.input.type == InputTypeShort) { // TODO: pause or fast-forward tamagotchi - tama_p1_save_state(); + tama_p1_save_state(); } else if(event.input.key == InputKeyUp) { // mute tamagotchi tamalib_set_button(BTN_LEFT, tama_btn_state); tamalib_set_button(BTN_RIGHT, tama_btn_state); @@ -500,7 +495,7 @@ int32_t tama_p1_app(void* p) { furi_timer_stop(timer); running = false; - tama_p1_save_state(); + tama_p1_save_state(); } } diff --git a/applications/services/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c index c1eb50d59..5239d72d5 100644 --- a/applications/services/desktop/animations/animation_manager.c +++ b/applications/services/desktop/animations/animation_manager.c @@ -145,7 +145,8 @@ void animation_manager_check_blocking_process(AnimationManager* animation_manage const StorageAnimationManifestInfo* manifest_info = animation_storage_get_meta(animation_manager->current_animation); - bool valid = animation_manager_is_valid_idle_animation(manifest_info, &stats, XTREME_SETTINGS()->unlock_anims); + bool valid = animation_manager_is_valid_idle_animation( + manifest_info, &stats, XTREME_SETTINGS()->unlock_anims); if(!valid) { animation_manager_start_new_idle(animation_manager); @@ -201,8 +202,10 @@ static void animation_manager_start_new_idle(AnimationManager* animation_manager animation_storage_get_bubble_animation(animation_manager->current_animation); animation_manager->state = AnimationManagerStateIdle; XtremeSettings* xtreme_settings = XTREME_SETTINGS(); - int32_t duration = (xtreme_settings->cycle_anims == 0) ? (bubble_animation->duration) : (xtreme_settings->cycle_anims); - furi_timer_start(animation_manager->idle_animation_timer, (duration > 0) ? (duration * 1000) : 0); + int32_t duration = (xtreme_settings->cycle_anims == 0) ? (bubble_animation->duration) : + (xtreme_settings->cycle_anims); + furi_timer_start( + animation_manager->idle_animation_timer, (duration > 0) ? (duration * 1000) : 0); } static bool animation_manager_check_blocking(AnimationManager* animation_manager) { @@ -355,7 +358,7 @@ static bool animation_manager_is_valid_idle_animation( result = (sd_status == FSE_NOT_READY); } - if (!unlock) { + if(!unlock) { if((stats->butthurt < info->min_butthurt) || (stats->butthurt > info->max_butthurt)) { result = false; } @@ -370,8 +373,9 @@ static bool animation_manager_is_valid_idle_animation( static StorageAnimation* animation_manager_select_idle_animation(AnimationManager* animation_manager) { const char* old_animation_name = NULL; - if (animation_manager->current_animation) { - old_animation_name = animation_storage_get_meta(animation_manager->current_animation)->name; + if(animation_manager->current_animation) { + old_animation_name = + animation_storage_get_meta(animation_manager->current_animation)->name; } StorageAnimationList_t animation_list; @@ -391,8 +395,8 @@ static StorageAnimation* animation_storage_get_meta(storage_animation); bool valid = animation_manager_is_valid_idle_animation(manifest_info, &stats, unlock); - if (old_animation_name != NULL) { - if (strcmp(manifest_info->name, old_animation_name) == 0) { + if(old_animation_name != NULL) { + if(strcmp(manifest_info->name, old_animation_name) == 0) { valid = false; } } @@ -512,7 +516,8 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m furi_record_close(RECORD_DOLPHIN); const StorageAnimationManifestInfo* manifest_info = animation_storage_get_meta(restore_animation); - bool valid = animation_manager_is_valid_idle_animation(manifest_info, &stats, XTREME_SETTINGS()->unlock_anims); + bool valid = animation_manager_is_valid_idle_animation( + manifest_info, &stats, XTREME_SETTINGS()->unlock_anims); if(valid) { animation_manager_replace_current_animation( animation_manager, restore_animation); @@ -523,12 +528,16 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m animation_manager->idle_animation_timer, animation_manager->freezed_animation_time_left); } else { - const BubbleAnimation* bubble_animation = animation_storage_get_bubble_animation( - animation_manager->current_animation); + const BubbleAnimation* bubble_animation = + animation_storage_get_bubble_animation( + animation_manager->current_animation); XtremeSettings* xtreme_settings = XTREME_SETTINGS(); - int32_t duration = (xtreme_settings->cycle_anims == 0) ? (bubble_animation->duration) : (xtreme_settings->cycle_anims); + int32_t duration = (xtreme_settings->cycle_anims == 0) ? + (bubble_animation->duration) : + (xtreme_settings->cycle_anims); furi_timer_start( - animation_manager->idle_animation_timer, (duration > 0) ? (duration * 1000) : 0); + animation_manager->idle_animation_timer, + (duration > 0) ? (duration * 1000) : 0); } } } else { diff --git a/applications/services/desktop/animations/animation_storage.c b/applications/services/desktop/animations/animation_storage.c index 28cdfe810..c717b0c36 100644 --- a/applications/services/desktop/animations/animation_storage.c +++ b/applications/services/desktop/animations/animation_storage.c @@ -35,18 +35,18 @@ void animation_handler_select_manifest() { FuriString* anim_dir = furi_string_alloc(); FuriString* manifest = furi_string_alloc(); bool use_asset_pack = xtreme_settings->asset_pack[0] != '\0'; - if (use_asset_pack) { + if(use_asset_pack) { furi_string_printf(anim_dir, "%s/%s/Anims", PACKS_DIR, xtreme_settings->asset_pack); furi_string_printf(manifest, "%s/manifest.txt", furi_string_get_cstr(anim_dir)); Storage* storage = furi_record_open(RECORD_STORAGE); - if (storage_common_stat(storage, furi_string_get_cstr(manifest), NULL) == FSE_OK) { + if(storage_common_stat(storage, furi_string_get_cstr(manifest), NULL) == FSE_OK) { FURI_LOG_I(TAG, "Custom Manifest selected"); } else { use_asset_pack = false; } furi_record_close(RECORD_STORAGE); } - if (!use_asset_pack) { + if(!use_asset_pack) { furi_string_set(anim_dir, BASE_ANIMATION_DIR); if(xtreme_settings->nsfw_mode) { furi_string_cat_str(anim_dir, "/nsfw"); @@ -58,7 +58,8 @@ void animation_handler_select_manifest() { furi_string_printf(manifest, "%s/manifest.txt", furi_string_get_cstr(anim_dir)); } strlcpy(ANIMATION_DIR, furi_string_get_cstr(anim_dir), sizeof(ANIMATION_DIR)); - strlcpy(ANIMATION_MANIFEST_FILE, furi_string_get_cstr(manifest), sizeof(ANIMATION_MANIFEST_FILE)); + strlcpy( + ANIMATION_MANIFEST_FILE, furi_string_get_cstr(manifest), sizeof(ANIMATION_MANIFEST_FILE)); furi_string_free(manifest); furi_string_free(anim_dir); } diff --git a/applications/services/desktop/views/desktop_view_lock_menu.c b/applications/services/desktop/views/desktop_view_lock_menu.c index 4cdfa54da..594676c28 100644 --- a/applications/services/desktop/views/desktop_view_lock_menu.c +++ b/applications/services/desktop/views/desktop_view_lock_menu.c @@ -68,7 +68,7 @@ void desktop_lock_menu_draw_callback(Canvas* canvas, void* model) { str = "Set PIN + Off"; } } else if(i == DesktopLockMenuIndexXtremeSettings) { - str = "Xtreme Settings"; + str = "Xtreme Settings"; } if(str) //-V547 diff --git a/applications/services/dolphin/helpers/dolphin_state.c b/applications/services/dolphin/helpers/dolphin_state.c index 72fa75ac0..419245a7c 100644 --- a/applications/services/dolphin/helpers/dolphin_state.c +++ b/applications/services/dolphin/helpers/dolphin_state.c @@ -15,9 +15,10 @@ #define DOLPHIN_STATE_HEADER_MAGIC 0xD0 #define DOLPHIN_STATE_HEADER_VERSION 0x01 -const int DOLPHIN_LEVELS[DOLPHIN_LEVEL_COUNT] = {100, 200, 300, 450, 600, 750, 950, 1150, 1350, 1600, - 1850, 2100, 2400, 2700, 3000, 3350, 3700, 4050, 4450, 4850, - 5250, 5700, 6150, 6600, 7100, 7600, 8100, 8650, 9200}; +const int DOLPHIN_LEVELS[DOLPHIN_LEVEL_COUNT] = {100, 200, 300, 450, 600, 750, 950, 1150, + 1350, 1600, 1850, 2100, 2400, 2700, 3000, 3350, + 3700, 4050, 4450, 4850, 5250, 5700, 6150, 6600, + 7100, 7600, 8100, 8650, 9200}; #define BUTTHURT_MAX 14 #define BUTTHURT_MIN 0 diff --git a/applications/services/power/power_service/power.c b/applications/services/power/power_service/power.c index f0f7735fb..e52cb4e10 100644 --- a/applications/services/power/power_service/power.c +++ b/applications/services/power/power_service/power.c @@ -26,7 +26,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) { snprintf(batteryPercentile, sizeof(batteryPercentile), "%d", power->info.charge); if((battery_style == BatteryStylePercent) && - (power->state != + (power->state != PowerStateCharging)) { //if display battery percentage, black background white text canvas_set_font(canvas, FontBatteryPercent); canvas_set_color(canvas, ColorBlack); @@ -36,7 +36,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) { } else if( (battery_style == BatteryStyleInvertedPercent) && (power->state != - PowerStateCharging)) { //if display inverted percentage, white background black text + PowerStateCharging)) { //if display inverted percentage, white background black text canvas_set_font(canvas, FontBatteryPercent); canvas_set_color(canvas, ColorBlack); canvas_draw_str_aligned(canvas, 11, 4, AlignCenter, AlignCenter, batteryPercentile); @@ -74,7 +74,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) { (battery_style == BatteryStyleBarPercent) && (power->state != PowerStateCharging) && // Default bar display with percentage (power->info.voltage_battery_charging >= - 4.2)) { // not looking nice with low voltage indicator + 4.2)) { // not looking nice with low voltage indicator canvas_set_font(canvas, FontBatteryPercent); // align charge dispaly value with digits to draw @@ -145,8 +145,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) { if(power->state == PowerStateCharging) { canvas_set_bitmap_mode(canvas, 1); // TODO: replace -1 magic for uint8_t with re-framing - if(battery_style == BatteryStylePercent || - battery_style == BatteryStyleBarPercent) { + if(battery_style == BatteryStylePercent || battery_style == BatteryStyleBarPercent) { canvas_set_color(canvas, ColorBlack); canvas_draw_box(canvas, 1, 1, 22, 6); canvas_draw_icon(canvas, 2, -1, &I_Charging_lightning_9x10); diff --git a/applications/settings/about/about.c b/applications/settings/about/about.c index 42712bc9c..918083265 100644 --- a/applications/settings/about/about.c +++ b/applications/settings/about/about.c @@ -222,9 +222,9 @@ static void draw_battery(Canvas* canvas, PowerInfo* info, int x, int y) { snprintf(header, sizeof(header), "Charged!"); } - if (!strcmp(value, "")) { + if(!strcmp(value, "")) { canvas_draw_str_aligned(canvas, x + 92, y + 14, AlignCenter, AlignCenter, header); - } else if (!strcmp(header, "")) { + } else if(!strcmp(header, "")) { canvas_draw_str_aligned(canvas, x + 92, y + 14, AlignCenter, AlignCenter, value); } else { canvas_draw_str_aligned(canvas, x + 92, y + 9, AlignCenter, AlignCenter, header); @@ -298,7 +298,6 @@ const AboutDialogScreen about_screens[] = { const int about_screens_count = sizeof(about_screens) / sizeof(AboutDialogScreen); - int32_t about_settings_app(void* p) { bool battery_info = false; if(p && strlen(p) && !strcmp(p, "batt")) { @@ -324,24 +323,19 @@ int32_t about_settings_app(void* p) { DialogMessageButton screen_result; // draw empty screen to prevent menu flickering - view_dispatcher_add_view( - view_dispatcher, battery_info_index, battery_view); + view_dispatcher_add_view(view_dispatcher, battery_info_index, battery_view); view_dispatcher_add_view( view_dispatcher, empty_screen_index, empty_screen_get_view(empty_screen)); view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); screen_index = -1 + !battery_info; while(screen_index > -2) { - - if (screen_index == -1) { - if (!battery_info) { + if(screen_index == -1) { + if(!battery_info) { break; } with_view_model( - battery_view, - PowerInfo * model, - { power_get_info(power, model); }, - true); + battery_view, PowerInfo * model, { power_get_info(power, model); }, true); view_dispatcher_switch_to_view(view_dispatcher, battery_info_index); furi_semaphore_acquire(semaphore, 2000); } else { @@ -360,7 +354,6 @@ int32_t about_settings_app(void* p) { screen_index = -2; } } - } dialog_message_free(message); diff --git a/applications/settings/dolphin_passport/passport.c b/applications/settings/dolphin_passport/passport.c index 3bea705ac..f0430de5d 100644 --- a/applications/settings/dolphin_passport/passport.c +++ b/applications/settings/dolphin_passport/passport.c @@ -67,7 +67,7 @@ static void render_callback(Canvas* canvas, void* _ctx) { uint32_t xp_need = dolphin_state_xp_to_levelup(stats->icounter); uint32_t xp_above_last_levelup = dolphin_state_xp_above_last_levelup(stats->icounter); uint32_t xp_levelup = 0; - if (ctx->progress_total) { + if(ctx->progress_total) { xp_levelup = xp_need + stats->icounter; } else { xp_levelup = xp_need + xp_above_last_levelup; diff --git a/applications/settings/xtreme_settings/scenes/xtreme_settings_scene_start.c b/applications/settings/xtreme_settings/scenes/xtreme_settings_scene_start.c index 90bdde83f..53d679efb 100644 --- a/applications/settings/xtreme_settings/scenes/xtreme_settings_scene_start.c +++ b/applications/settings/xtreme_settings/scenes/xtreme_settings_scene_start.c @@ -15,8 +15,12 @@ static void xtreme_settings_scene_start_base_graphics_changed(VariableItem* item static void xtreme_settings_scene_start_asset_pack_changed(VariableItem* item) { XtremeSettingsApp* app = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, index == 0 ? "OFF" : *asset_packs_get(app->asset_packs, index - 1)); - strlcpy(XTREME_SETTINGS()->asset_pack, index == 0 ? "" : *asset_packs_get(app->asset_packs, index - 1), MAX_PACK_NAME_LEN); + variable_item_set_current_value_text( + item, index == 0 ? "OFF" : *asset_packs_get(app->asset_packs, index - 1)); + strlcpy( + XTREME_SETTINGS()->asset_pack, + index == 0 ? "" : *asset_packs_get(app->asset_packs, index - 1), + MAX_PACK_NAME_LEN); app->settings_changed = true; app->assets_changed = true; } @@ -33,8 +37,20 @@ static void xtreme_settings_scene_start_anim_speed_changed(VariableItem* item) { app->settings_changed = true; } -const char* const cycle_anims_names[] = - {"OFF", "Meta.txt", "30 S", "1 M", "5 M", "10 M", "15 M", "30 M", "1 H", "2 H", "6 H", "12 H", "24 H"}; +const char* const cycle_anims_names[] = { + "OFF", + "Meta.txt", + "30 S", + "1 M", + "5 M", + "10 M", + "15 M", + "30 M", + "1 H", + "2 H", + "6 H", + "12 H", + "24 H"}; const int32_t cycle_anims_values[COUNT_OF(cycle_anims_names)] = {-1, 0, 30, 60, 300, 600, 900, 1800, 3600, 7200, 21600, 43200, 86400}; static void xtreme_settings_scene_start_cycle_anims_changed(VariableItem* item) { @@ -62,8 +78,7 @@ const int32_t battery_style_values[COUNT_OF(battery_style_names)] = { BatteryStyleInvertedPercent, BatteryStyleRetro3, BatteryStyleRetro5, - BatteryStyleBarPercent -}; + BatteryStyleBarPercent}; static void xtreme_settings_scene_start_battery_style_changed(VariableItem* item) { XtremeSettingsApp* app = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); @@ -112,7 +127,8 @@ void xtreme_settings_scene_start_on_enter(void* context) { app->subghz_extend = false; app->subghz_bypass = false; if(flipper_format_file_open_existing(subghz_range, "/ext/subghz/assets/extend_range.txt")) { - flipper_format_read_bool(subghz_range, "use_ext_range_at_own_risk", &app->subghz_extend, 1); + flipper_format_read_bool( + subghz_range, "use_ext_range_at_own_risk", &app->subghz_extend, 1); flipper_format_read_bool(subghz_range, "ignore_default_tx_region", &app->subghz_bypass, 1); } flipper_format_free(subghz_range); @@ -123,14 +139,15 @@ void xtreme_settings_scene_start_on_enter(void* context) { FileInfo info; char* name = malloc(MAX_PACK_NAME_LEN); do { - if (!storage_dir_open(folder, PACKS_DIR)) break; + if(!storage_dir_open(folder, PACKS_DIR)) break; while(true) { - if (!storage_dir_read(folder, &info, name, MAX_PACK_NAME_LEN)) break; + if(!storage_dir_read(folder, &info, name, MAX_PACK_NAME_LEN)) break; if(info.flags & FSF_DIRECTORY) { char* copy = malloc(MAX_PACK_NAME_LEN); strlcpy(copy, name, MAX_PACK_NAME_LEN); asset_packs_push_back(app->asset_packs, copy); - if (strcmp(name, xtreme_settings->asset_pack) == 0) current_pack = asset_packs_size(app->asset_packs); + if(strcmp(name, xtreme_settings->asset_pack) == 0) + current_pack = asset_packs_size(app->asset_packs); } } } while(false); @@ -139,11 +156,7 @@ void xtreme_settings_scene_start_on_enter(void* context) { furi_record_close(RECORD_STORAGE); item = variable_item_list_add( - var_item_list, - "Base Graphics", - 2, - xtreme_settings_scene_start_base_graphics_changed, - app); + var_item_list, "Base Graphics", 2, xtreme_settings_scene_start_base_graphics_changed, app); variable_item_set_current_value_index(item, xtreme_settings->nsfw_mode); variable_item_set_current_value_text(item, xtreme_settings->nsfw_mode ? "NSFW" : "SFW"); @@ -154,7 +167,8 @@ void xtreme_settings_scene_start_on_enter(void* context) { xtreme_settings_scene_start_asset_pack_changed, app); variable_item_set_current_value_index(item, current_pack); - variable_item_set_current_value_text(item, current_pack == 0 ? "OFF" : *asset_packs_get(app->asset_packs, current_pack - 1)); + variable_item_set_current_value_text( + item, current_pack == 0 ? "OFF" : *asset_packs_get(app->asset_packs, current_pack - 1)); item = variable_item_list_add( var_item_list, @@ -179,11 +193,7 @@ void xtreme_settings_scene_start_on_enter(void* context) { variable_item_set_current_value_text(item, cycle_anims_names[value_index]); item = variable_item_list_add( - var_item_list, - "Unlock Anims", - 2, - xtreme_settings_scene_start_unlock_anims_changed, - app); + var_item_list, "Unlock Anims", 2, xtreme_settings_scene_start_unlock_anims_changed, app); variable_item_set_current_value_index(item, xtreme_settings->unlock_anims); variable_item_set_current_value_text(item, xtreme_settings->unlock_anims ? "ON" : "OFF"); @@ -210,30 +220,18 @@ void xtreme_settings_scene_start_on_enter(void* context) { variable_item_set_current_value_text(item, level_str); item = variable_item_list_add( - var_item_list, - "SubGHz Extend", - 2, - xtreme_settings_scene_start_subghz_extend_changed, - app); + var_item_list, "SubGHz Extend", 2, xtreme_settings_scene_start_subghz_extend_changed, app); variable_item_set_current_value_index(item, app->subghz_extend); variable_item_set_current_value_text(item, app->subghz_extend ? "ON" : "OFF"); item = variable_item_list_add( - var_item_list, - "SubGHz Bypass", - 2, - xtreme_settings_scene_start_subghz_bypass_changed, - app); + var_item_list, "SubGHz Bypass", 2, xtreme_settings_scene_start_subghz_bypass_changed, app); variable_item_set_current_value_index(item, app->subghz_bypass); variable_item_set_current_value_text(item, app->subghz_bypass ? "ON" : "OFF"); - FuriString* version_tag = furi_string_alloc_printf("%s %s", version_get_gitbranchnum(NULL), version_get_builddate(NULL)); - item = variable_item_list_add( - var_item_list, - furi_string_get_cstr(version_tag), - 0, - NULL, - app); + FuriString* version_tag = furi_string_alloc_printf( + "%s %s", version_get_gitbranchnum(NULL), version_get_builddate(NULL)); + item = variable_item_list_add(var_item_list, furi_string_get_cstr(version_tag), 0, NULL, app); view_dispatcher_switch_to_view(app->view_dispatcher, XtremeSettingsAppViewVarItemList); } @@ -248,7 +246,7 @@ bool xtreme_settings_scene_start_on_event(void* context, SceneManagerEvent event void xtreme_settings_scene_start_on_exit(void* context) { XtremeSettingsApp* app = context; asset_packs_it_t it; - for (asset_packs_it(it, app->asset_packs); !asset_packs_end_p(it); asset_packs_next(it)) { + for(asset_packs_it(it, app->asset_packs); !asset_packs_end_p(it); asset_packs_next(it)) { free(*asset_packs_cref(it)); } asset_packs_clear(app->asset_packs); diff --git a/applications/settings/xtreme_settings/xtreme_assets.c b/applications/settings/xtreme_settings/xtreme_assets.c index 444b50951..0f6ab998d 100644 --- a/applications/settings/xtreme_settings/xtreme_assets.c +++ b/applications/settings/xtreme_settings/xtreme_assets.c @@ -5,94 +5,158 @@ XtremeAssets* xtreme_assets = NULL; XtremeAssets* XTREME_ASSETS() { - if (xtreme_assets == NULL) { + if(xtreme_assets == NULL) { XTREME_ASSETS_LOAD(); } return xtreme_assets; } void XTREME_ASSETS_LOAD() { - if (xtreme_assets != NULL) return; + if(xtreme_assets != NULL) return; xtreme_assets = malloc(sizeof(XtremeAssets)); XtremeSettings* xtreme_settings = XTREME_SETTINGS(); - if (xtreme_settings->nsfw_mode) { - xtreme_assets->I_BLE_Pairing_128x64 = &I_BLE_Pairing_128x64; - xtreme_assets->I_DolphinCommon_56x48 = &I_DolphinCommon_56x48; - xtreme_assets->I_DolphinMafia_115x62 = &I_DolphinMafia_115x62; - xtreme_assets->I_DolphinNice_96x59 = &I_DolphinNice_96x59; - xtreme_assets->I_DolphinWait_61x59 = &I_DolphinWait_61x59; + if(xtreme_settings->nsfw_mode) { + xtreme_assets->I_BLE_Pairing_128x64 = &I_BLE_Pairing_128x64; + xtreme_assets->I_DolphinCommon_56x48 = &I_DolphinCommon_56x48; + xtreme_assets->I_DolphinMafia_115x62 = &I_DolphinMafia_115x62; + xtreme_assets->I_DolphinNice_96x59 = &I_DolphinNice_96x59; + xtreme_assets->I_DolphinWait_61x59 = &I_DolphinWait_61x59; xtreme_assets->I_iButtonDolphinVerySuccess_108x52 = &I_iButtonDolphinVerySuccess_108x52; - xtreme_assets->I_DolphinReadingSuccess_59x63 = &I_DolphinReadingSuccess_59x63; - xtreme_assets->I_NFC_dolphin_emulation_47x61 = &I_NFC_dolphin_emulation_47x61; - xtreme_assets->I_passport_bad_46x49 = &I_flipper; - xtreme_assets->I_passport_DB = &I_passport_DB; - xtreme_assets->I_passport_happy_46x49 = &I_flipper; - xtreme_assets->I_passport_okay_46x49 = &I_flipper; - xtreme_assets->I_RFIDDolphinReceive_97x61 = &I_RFIDDolphinReceive_97x61; - xtreme_assets->I_RFIDDolphinSend_97x61 = &I_RFIDDolphinSend_97x61; - xtreme_assets->I_RFIDDolphinSuccess_108x57 = &I_RFIDDolphinSuccess_108x57; - xtreme_assets->I_Cry_dolph_55x52 = &I_Cry_dolph_55x52; - xtreme_assets->I_Scanning_123x52 = &I_Scanning_123x52; - xtreme_assets->I_Auth_62x31 = &I_Auth_62x31; - xtreme_assets->I_Connect_me_62x31 = &I_Connect_me_62x31; - xtreme_assets->I_Connected_62x31 = &I_Connected_62x31; - xtreme_assets->I_Error_62x31 = &I_Error_62x31; + xtreme_assets->I_DolphinReadingSuccess_59x63 = &I_DolphinReadingSuccess_59x63; + xtreme_assets->I_NFC_dolphin_emulation_47x61 = &I_NFC_dolphin_emulation_47x61; + xtreme_assets->I_passport_bad_46x49 = &I_flipper; + xtreme_assets->I_passport_DB = &I_passport_DB; + xtreme_assets->I_passport_happy_46x49 = &I_flipper; + xtreme_assets->I_passport_okay_46x49 = &I_flipper; + xtreme_assets->I_RFIDDolphinReceive_97x61 = &I_RFIDDolphinReceive_97x61; + xtreme_assets->I_RFIDDolphinSend_97x61 = &I_RFIDDolphinSend_97x61; + xtreme_assets->I_RFIDDolphinSuccess_108x57 = &I_RFIDDolphinSuccess_108x57; + xtreme_assets->I_Cry_dolph_55x52 = &I_Cry_dolph_55x52; + xtreme_assets->I_Scanning_123x52 = &I_Scanning_123x52; + xtreme_assets->I_Auth_62x31 = &I_Auth_62x31; + xtreme_assets->I_Connect_me_62x31 = &I_Connect_me_62x31; + xtreme_assets->I_Connected_62x31 = &I_Connected_62x31; + xtreme_assets->I_Error_62x31 = &I_Error_62x31; } else { - xtreme_assets->I_BLE_Pairing_128x64 = &I_BLE_Pairing_128x64_sfw; - xtreme_assets->I_DolphinCommon_56x48 = &I_DolphinCommon_56x48_sfw; - xtreme_assets->I_DolphinMafia_115x62 = &I_DolphinMafia_115x62_sfw; - xtreme_assets->I_DolphinNice_96x59 = &I_DolphinNice_96x59_sfw; - xtreme_assets->I_DolphinWait_61x59 = &I_DolphinWait_61x59_sfw; - xtreme_assets->I_iButtonDolphinVerySuccess_108x52 = &I_iButtonDolphinVerySuccess_108x52_sfw; - xtreme_assets->I_DolphinReadingSuccess_59x63 = &I_DolphinReadingSuccess_59x63_sfw; - xtreme_assets->I_NFC_dolphin_emulation_47x61 = &I_NFC_dolphin_emulation_47x61_sfw; - xtreme_assets->I_passport_bad_46x49 = &I_passport_bad1_46x49_sfw; - xtreme_assets->I_passport_DB = &I_passport_DB_sfw; - xtreme_assets->I_passport_happy_46x49 = &I_passport_happy1_46x49_sfw; - xtreme_assets->I_passport_okay_46x49 = &I_passport_okay1_46x49_sfw; - xtreme_assets->I_RFIDDolphinReceive_97x61 = &I_RFIDDolphinReceive_97x61_sfw; - xtreme_assets->I_RFIDDolphinSend_97x61 = &I_RFIDDolphinSend_97x61_sfw; - xtreme_assets->I_RFIDDolphinSuccess_108x57 = &I_RFIDDolphinSuccess_108x57_sfw; - xtreme_assets->I_Cry_dolph_55x52 = &I_Cry_dolph_55x52_sfw; - xtreme_assets->I_Scanning_123x52 = &I_Scanning_123x52_sfw; - xtreme_assets->I_Auth_62x31 = &I_Auth_62x31_sfw; - xtreme_assets->I_Connect_me_62x31 = &I_Connect_me_62x31_sfw; - xtreme_assets->I_Connected_62x31 = &I_Connected_62x31_sfw; - xtreme_assets->I_Error_62x31 = &I_Error_62x31_sfw; + xtreme_assets->I_BLE_Pairing_128x64 = &I_BLE_Pairing_128x64_sfw; + xtreme_assets->I_DolphinCommon_56x48 = &I_DolphinCommon_56x48_sfw; + xtreme_assets->I_DolphinMafia_115x62 = &I_DolphinMafia_115x62_sfw; + xtreme_assets->I_DolphinNice_96x59 = &I_DolphinNice_96x59_sfw; + xtreme_assets->I_DolphinWait_61x59 = &I_DolphinWait_61x59_sfw; + xtreme_assets->I_iButtonDolphinVerySuccess_108x52 = + &I_iButtonDolphinVerySuccess_108x52_sfw; + xtreme_assets->I_DolphinReadingSuccess_59x63 = &I_DolphinReadingSuccess_59x63_sfw; + xtreme_assets->I_NFC_dolphin_emulation_47x61 = &I_NFC_dolphin_emulation_47x61_sfw; + xtreme_assets->I_passport_bad_46x49 = &I_passport_bad1_46x49_sfw; + xtreme_assets->I_passport_DB = &I_passport_DB_sfw; + xtreme_assets->I_passport_happy_46x49 = &I_passport_happy1_46x49_sfw; + xtreme_assets->I_passport_okay_46x49 = &I_passport_okay1_46x49_sfw; + xtreme_assets->I_RFIDDolphinReceive_97x61 = &I_RFIDDolphinReceive_97x61_sfw; + xtreme_assets->I_RFIDDolphinSend_97x61 = &I_RFIDDolphinSend_97x61_sfw; + xtreme_assets->I_RFIDDolphinSuccess_108x57 = &I_RFIDDolphinSuccess_108x57_sfw; + xtreme_assets->I_Cry_dolph_55x52 = &I_Cry_dolph_55x52_sfw; + xtreme_assets->I_Scanning_123x52 = &I_Scanning_123x52_sfw; + xtreme_assets->I_Auth_62x31 = &I_Auth_62x31_sfw; + xtreme_assets->I_Connect_me_62x31 = &I_Connect_me_62x31_sfw; + xtreme_assets->I_Connected_62x31 = &I_Connected_62x31_sfw; + xtreme_assets->I_Error_62x31 = &I_Error_62x31_sfw; } - if (xtreme_settings->asset_pack[0] == '\0') return; + if(xtreme_settings->asset_pack[0] == '\0') return; FileInfo info; FuriString* path = furi_string_alloc(); const char* pack = xtreme_settings->asset_pack; furi_string_printf(path, PACKS_DIR "/%s", pack); Storage* storage = furi_record_open(RECORD_STORAGE); - if (storage_common_stat(storage, furi_string_get_cstr(path), &info) == FSE_OK && info.flags & FSF_DIRECTORY) { + if(storage_common_stat(storage, furi_string_get_cstr(path), &info) == FSE_OK && + info.flags & FSF_DIRECTORY) { File* file = storage_file_alloc(storage); - swap_bmx_icon(&xtreme_assets->I_BLE_Pairing_128x64, pack, "BLE/BLE_Pairing_128x64.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_DolphinCommon_56x48, pack, "Dolphin/DolphinCommon_56x48.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_DolphinMafia_115x62, pack, "iButton/DolphinMafia_115x62.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_DolphinNice_96x59, pack, "iButton/DolphinNice_96x59.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_DolphinWait_61x59, pack, "iButton/DolphinWait_61x59.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_iButtonDolphinVerySuccess_108x52, pack, "iButton/iButtonDolphinVerySuccess_108x52.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_DolphinReadingSuccess_59x63, pack, "Infrared/DolphinReadingSuccess_59x63.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_NFC_dolphin_emulation_47x61, pack, "NFC/NFC_dolphin_emulation_47x61.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_passport_bad_46x49, pack, "Passport/passport_bad_46x49.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_passport_DB, pack, "Passport/passport_DB.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_passport_happy_46x49, pack, "Passport/passport_happy_46x49.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_passport_okay_46x49, pack, "Passport/passport_okay_46x49.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_RFIDDolphinReceive_97x61, pack, "RFID/RFIDDolphinReceive_97x61.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_RFIDDolphinSend_97x61, pack, "RFID/RFIDDolphinSend_97x61.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_RFIDDolphinSuccess_108x57, pack, "RFID/RFIDDolphinSuccess_108x57.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_Cry_dolph_55x52, pack, "Settings/Cry_dolph_55x52.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_Scanning_123x52, pack, "SubGhz/Scanning_123x52.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_Auth_62x31, pack, "U2F/Auth_62x31.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_Connect_me_62x31, pack, "U2F/Connect_me_62x31.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_Connected_62x31, pack, "U2F/Connected_62x31.bmx", path, file); - swap_bmx_icon(&xtreme_assets->I_Error_62x31, pack, "U2F/Error_62x31.bmx", path, file); + swap_bmx_icon( + &xtreme_assets->I_BLE_Pairing_128x64, pack, "BLE/BLE_Pairing_128x64.bmx", path, file); + swap_bmx_icon( + &xtreme_assets->I_DolphinCommon_56x48, + pack, + "Dolphin/DolphinCommon_56x48.bmx", + path, + file); + swap_bmx_icon( + &xtreme_assets->I_DolphinMafia_115x62, + pack, + "iButton/DolphinMafia_115x62.bmx", + path, + file); + swap_bmx_icon( + &xtreme_assets->I_DolphinNice_96x59, pack, "iButton/DolphinNice_96x59.bmx", path, file); + swap_bmx_icon( + &xtreme_assets->I_DolphinWait_61x59, pack, "iButton/DolphinWait_61x59.bmx", path, file); + swap_bmx_icon( + &xtreme_assets->I_iButtonDolphinVerySuccess_108x52, + pack, + "iButton/iButtonDolphinVerySuccess_108x52.bmx", + path, + file); + swap_bmx_icon( + &xtreme_assets->I_DolphinReadingSuccess_59x63, + pack, + "Infrared/DolphinReadingSuccess_59x63.bmx", + path, + file); + swap_bmx_icon( + &xtreme_assets->I_NFC_dolphin_emulation_47x61, + pack, + "NFC/NFC_dolphin_emulation_47x61.bmx", + path, + file); + swap_bmx_icon( + &xtreme_assets->I_passport_bad_46x49, + pack, + "Passport/passport_bad_46x49.bmx", + path, + file); + swap_bmx_icon(&xtreme_assets->I_passport_DB, pack, "Passport/passport_DB.bmx", path, file); + swap_bmx_icon( + &xtreme_assets->I_passport_happy_46x49, + pack, + "Passport/passport_happy_46x49.bmx", + path, + file); + swap_bmx_icon( + &xtreme_assets->I_passport_okay_46x49, + pack, + "Passport/passport_okay_46x49.bmx", + path, + file); + swap_bmx_icon( + &xtreme_assets->I_RFIDDolphinReceive_97x61, + pack, + "RFID/RFIDDolphinReceive_97x61.bmx", + path, + file); + swap_bmx_icon( + &xtreme_assets->I_RFIDDolphinSend_97x61, + pack, + "RFID/RFIDDolphinSend_97x61.bmx", + path, + file); + swap_bmx_icon( + &xtreme_assets->I_RFIDDolphinSuccess_108x57, + pack, + "RFID/RFIDDolphinSuccess_108x57.bmx", + path, + file); + swap_bmx_icon( + &xtreme_assets->I_Cry_dolph_55x52, pack, "Settings/Cry_dolph_55x52.bmx", path, file); + swap_bmx_icon( + &xtreme_assets->I_Scanning_123x52, pack, "SubGhz/Scanning_123x52.bmx", path, file); + swap_bmx_icon(&xtreme_assets->I_Auth_62x31, pack, "U2F/Auth_62x31.bmx", path, file); + swap_bmx_icon( + &xtreme_assets->I_Connect_me_62x31, pack, "U2F/Connect_me_62x31.bmx", path, file); + swap_bmx_icon( + &xtreme_assets->I_Connected_62x31, pack, "U2F/Connected_62x31.bmx", path, file); + swap_bmx_icon(&xtreme_assets->I_Error_62x31, pack, "U2F/Error_62x31.bmx", path, file); storage_file_free(file); } @@ -100,9 +164,14 @@ void XTREME_ASSETS_LOAD() { furi_string_free(path); } -void swap_bmx_icon(const Icon** replace, const char* pack, const char* name, FuriString* path, File* file) { +void swap_bmx_icon( + const Icon** replace, + const char* pack, + const char* name, + FuriString* path, + File* file) { furi_string_printf(path, PACKS_DIR "/%s/Icons/%s", pack, name); - if (storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { + if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { uint64_t size = storage_file_size(file) - 8; int32_t width, height; storage_file_read(file, &width, 4); diff --git a/applications/settings/xtreme_settings/xtreme_assets.h b/applications/settings/xtreme_settings/xtreme_assets.h index df618c47d..c49f5b590 100644 --- a/applications/settings/xtreme_settings/xtreme_assets.h +++ b/applications/settings/xtreme_settings/xtreme_assets.h @@ -34,6 +34,11 @@ XtremeAssets* XTREME_ASSETS(); void XTREME_ASSETS_LOAD(); -void swap_bmx_icon(const Icon** replace, const char* base, const char* name, FuriString* path, File* file); +void swap_bmx_icon( + const Icon** replace, + const char* base, + const char* name, + FuriString* path, + File* file); void free_bmx_icon(Icon* icon); diff --git a/applications/settings/xtreme_settings/xtreme_settings.c b/applications/settings/xtreme_settings/xtreme_settings.c index 84018bcf0..3db0a4c1c 100644 --- a/applications/settings/xtreme_settings/xtreme_settings.c +++ b/applications/settings/xtreme_settings/xtreme_settings.c @@ -3,17 +3,21 @@ XtremeSettings* xtreme_settings = NULL; XtremeSettings* XTREME_SETTINGS() { - if (xtreme_settings == NULL) { + if(xtreme_settings == NULL) { XTREME_SETTINGS_LOAD(); } return xtreme_settings; } bool XTREME_SETTINGS_LOAD() { - if (xtreme_settings == NULL) { + if(xtreme_settings == NULL) { xtreme_settings = malloc(sizeof(XtremeSettings)); bool loaded = saved_struct_load( - XTREME_SETTINGS_PATH, xtreme_settings, sizeof(XtremeSettings), XTREME_SETTINGS_MAGIC, XTREME_SETTINGS_VERSION); + XTREME_SETTINGS_PATH, + xtreme_settings, + sizeof(XtremeSettings), + XTREME_SETTINGS_MAGIC, + XTREME_SETTINGS_VERSION); if(!loaded) { memset(xtreme_settings, 0, sizeof(XtremeSettings)); loaded = XTREME_SETTINGS_SAVE(); @@ -24,9 +28,13 @@ bool XTREME_SETTINGS_LOAD() { } bool XTREME_SETTINGS_SAVE() { - if (xtreme_settings == NULL) { + if(xtreme_settings == NULL) { XTREME_SETTINGS_LOAD(); } return saved_struct_save( - XTREME_SETTINGS_PATH, xtreme_settings, sizeof(XtremeSettings), XTREME_SETTINGS_MAGIC, XTREME_SETTINGS_VERSION); + XTREME_SETTINGS_PATH, + xtreme_settings, + sizeof(XtremeSettings), + XTREME_SETTINGS_MAGIC, + XTREME_SETTINGS_VERSION); } diff --git a/applications/settings/xtreme_settings/xtreme_settings_app.c b/applications/settings/xtreme_settings/xtreme_settings_app.c index 780e76730..6b0a12f1c 100644 --- a/applications/settings/xtreme_settings/xtreme_settings_app.c +++ b/applications/settings/xtreme_settings/xtreme_settings_app.c @@ -15,10 +15,10 @@ static bool xtreme_settings_back_event_callback(void* context) { furi_assert(context); XtremeSettingsApp* app = context; - if (app->level_changed) { + if(app->level_changed) { Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN); DolphinStats stats = dolphin_stats(dolphin); - if (app->dolphin_level != stats.level) { + if(app->dolphin_level != stats.level) { int xp = app->dolphin_level > 1 ? dolphin_get_levels()[app->dolphin_level - 2] : 0; dolphin->state->data.icounter = xp + 1; dolphin->state->dirty = true; @@ -27,20 +27,22 @@ static bool xtreme_settings_back_event_callback(void* context) { furi_record_close(RECORD_DOLPHIN); } - if (app->subghz_changed) { + if(app->subghz_changed) { Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* subghz_range = flipper_format_file_alloc(storage); if(flipper_format_file_open_existing(subghz_range, "/ext/subghz/assets/extend_range.txt")) { - flipper_format_insert_or_update_bool(subghz_range, "use_ext_range_at_own_risk", &app->subghz_extend, 1); - flipper_format_insert_or_update_bool(subghz_range, "ignore_default_tx_region", &app->subghz_bypass, 1); + flipper_format_insert_or_update_bool( + subghz_range, "use_ext_range_at_own_risk", &app->subghz_extend, 1); + flipper_format_insert_or_update_bool( + subghz_range, "ignore_default_tx_region", &app->subghz_bypass, 1); } flipper_format_free(subghz_range); furi_record_close(RECORD_STORAGE); } - if (app->settings_changed) { + if(app->settings_changed) { XTREME_SETTINGS_SAVE(); - if (app->assets_changed) { + if(app->assets_changed) { popup_set_header(app->popup, "Rebooting...", 64, 26, AlignCenter, AlignCenter); popup_set_text(app->popup, "Swapping assets...", 64, 40, AlignCenter, AlignCenter); popup_set_callback(app->popup, xtreme_settings_reboot); @@ -81,9 +83,7 @@ XtremeSettingsApp* xtreme_settings_app_alloc() { app->popup = popup_alloc(); view_dispatcher_add_view( - app->view_dispatcher, - XtremeSettingsAppViewPopup, - popup_get_view(app->popup)); + app->view_dispatcher, XtremeSettingsAppViewPopup, popup_get_view(app->popup)); // Set first scene scene_manager_next_scene(app->scene_manager, XtremeSettingsAppSceneStart); From d833d6dbb24daf6ba1a3962f815c93741d602713 Mon Sep 17 00:00:00 2001 From: WillyJL Date: Fri, 27 Jan 2023 02:11:53 +0000 Subject: [PATCH 20/26] Update build.yml --- .github/workflows/build.yml | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 99f80fefa..773fe8d1d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -80,12 +80,46 @@ jobs: run: | cp build/core2_firmware.tgz "artifacts/flipper-z-any-core2_firmware-${SUFFIX}.tgz" - - name: 'Archive artifacts' + - name: 'Firmware artifact' uses: actions/upload-artifact@v3 with: name: firmware path: | artifacts + + - name: 'Updater artifact' + uses: actions/upload-artifact@v3 + with: + name: updater + path: | + artifacts/f7-* + + - name: Artifact info + id: artifact-info + uses: dawidd6/action-download-artifact@v2 + with: + name: updater + dry_run: true + + - name: 'Find Previous Comment' + if: ${{ github.event.pull_request }} + uses: peter-evans/find-comment@v1 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: 'Compiled firmware for commit' + + - name: 'Create or update comment' + if: ${{ github.event.pull_request}} + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + **Compiled firmware for commit `${{steps.names.outputs.commit_sha}}`:** + - [📦 Update package](${{steps.artifact-info.outputs.artifacts[0].archive_download_url}}) + edit-mode: replace compact: if: ${{ !startsWith(github.ref, 'refs/tags') }} From c382f9d110b3176dd4ffa8edec4a84fef2fb2512 Mon Sep 17 00:00:00 2001 From: WillyJL Date: Fri, 27 Jan 2023 02:25:27 +0000 Subject: [PATCH 21/26] Update build.yml --- .github/workflows/build.yml | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 773fe8d1d..5b19d123b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -80,13 +80,6 @@ jobs: run: | cp build/core2_firmware.tgz "artifacts/flipper-z-any-core2_firmware-${SUFFIX}.tgz" - - name: 'Firmware artifact' - uses: actions/upload-artifact@v3 - with: - name: firmware - path: | - artifacts - - name: 'Updater artifact' uses: actions/upload-artifact@v3 with: @@ -94,12 +87,12 @@ jobs: path: | artifacts/f7-* - - name: Artifact info - id: artifact-info - uses: dawidd6/action-download-artifact@v2 + - name: 'Firmware artifact' + uses: actions/upload-artifact@v3 with: - name: updater - dry_run: true + name: firmware + path: | + artifacts - name: 'Find Previous Comment' if: ${{ github.event.pull_request }} @@ -109,6 +102,12 @@ jobs: issue-number: ${{ github.event.pull_request.number }} comment-author: 'github-actions[bot]' body-includes: 'Compiled firmware for commit' + + - name: Artifact info + id: artifact-info + uses: dawidd6/action-download-artifact@v2 + with: + dry_run: true - name: 'Create or update comment' if: ${{ github.event.pull_request}} From 8fc834090d289ad75de8261ad69ec310a39b5834 Mon Sep 17 00:00:00 2001 From: Krzysztof Zdulski Date: Fri, 27 Jan 2023 06:00:25 +0100 Subject: [PATCH 22/26] nfc: Fix sector reads when one block is unreadable for MIFARE Classic (#2296) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix sector reads when one block is unreadable * Auth on the correct block instead of first * Fix in sector reader as well * Apply patch by @gornekich Co-authored-by: gornekich Co-authored-by: あく --- lib/nfc/protocols/mifare_classic.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index c91e9c605..d1aadf06f 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -595,6 +595,14 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) { mf_classic_set_block_read(data, i, &block_tmp); blocks_read++; + } else if(i > start_block) { + // Try to re-auth to read block in case prevous block was protected from read + furi_hal_nfc_sleep(); + if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyA, &crypto, false, 0)) break; + if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) { + mf_classic_set_block_read(data, i, &block_tmp); + blocks_read++; + } } } else { blocks_read++; @@ -607,13 +615,20 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u if(!key_b_found) break; FURI_LOG_D(TAG, "Try to read blocks with key B"); key = nfc_util_bytes2num(sec_tr->key_b, sizeof(sec_tr->key_b)); - furi_hal_nfc_sleep(); if(!mf_classic_auth(tx_rx, start_block, key, MfClassicKeyB, &crypto, false, 0)) break; for(size_t i = start_block; i < start_block + total_blocks; i++) { if(!mf_classic_is_block_read(data, i)) { if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) { mf_classic_set_block_read(data, i, &block_tmp); blocks_read++; + } else if(i > start_block) { + // Try to re-auth to read block in case prevous block was protected from read + furi_hal_nfc_sleep(); + if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyB, &crypto, false, 0)) break; + if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) { + mf_classic_set_block_read(data, i, &block_tmp); + blocks_read++; + } } } else { blocks_read++; @@ -665,6 +680,11 @@ static bool mf_classic_read_sector_with_reader( // Read blocks for(uint8_t i = 0; i < sector->total_blocks; i++) { + if(mf_classic_read_block(tx_rx, crypto, first_block + i, §or->block[i])) continue; + if(i == 0) continue; + // Try to auth to read next block in case previous is locked + furi_hal_nfc_sleep(); + if(!mf_classic_auth(tx_rx, first_block + i, key, key_type, crypto, false, 0)) continue; mf_classic_read_block(tx_rx, crypto, first_block + i, §or->block[i]); } // Save sector keys in last block From 4dc4d34d04c4d998ba5e05a2bca8a6d17aeefd01 Mon Sep 17 00:00:00 2001 From: Emily Trau Date: Fri, 27 Jan 2023 16:10:08 +1100 Subject: [PATCH 23/26] emv: parse track1&2 equivalent data (#2332) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * emv: parse track1&2 equivalent data * emv: alternate expiry parser * nfc: log EMV track1&2 data to trace output Co-authored-by: gornekich Co-authored-by: あく --- lib/nfc/protocols/emv.c | 35 +++++++++++++++++++++++++++++------ lib/nfc/protocols/emv.h | 3 ++- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/nfc/protocols/emv.c b/lib/nfc/protocols/emv.c index e00d09e70..4c4ac856b 100644 --- a/lib/nfc/protocols/emv.c +++ b/lib/nfc/protocols/emv.c @@ -142,21 +142,44 @@ static bool emv_decode_response(uint8_t* buff, uint16_t len, EmvApplication* app success = true; FURI_LOG_T(TAG, "found EMV_TAG_AFL %x (len=%d)", tag, tlen); break; - case EMV_TAG_CARD_NUM: // Track 2 Equivalent Data. 0xD0 delimits PAN from expiry (YYMM) + case EMV_TAG_TRACK_1_EQUIV: { + char track_1_equiv[80]; + memcpy(track_1_equiv, &buff[i], tlen); + track_1_equiv[tlen] = '\0'; + success = true; + FURI_LOG_T(TAG, "found EMV_TAG_TRACK_1_EQUIV %x : %s", tag, track_1_equiv); + break; + } + case EMV_TAG_TRACK_2_EQUIV: { + // 0xD0 delimits PAN from expiry (YYMM) for(int x = 1; x < tlen; x++) { if(buff[i + x + 1] > 0xD0) { memcpy(app->card_number, &buff[i], x + 1); app->card_number_len = x + 1; + app->exp_year = (buff[i + x + 1] << 4) | (buff[i + x + 2] >> 4); + app->exp_month = (buff[i + x + 2] << 4) | (buff[i + x + 3] >> 4); break; } } + + // Convert 4-bit to ASCII representation + char track_2_equiv[41]; + uint8_t track_2_equiv_len = 0; + for(int x = 0; x < tlen; x++) { + char top = (buff[i + x] >> 4) + '0'; + char bottom = (buff[i + x] & 0x0F) + '0'; + track_2_equiv[x * 2] = top; + track_2_equiv_len++; + if(top == '?') break; + track_2_equiv[x * 2 + 1] = bottom; + track_2_equiv_len++; + if(bottom == '?') break; + } + track_2_equiv[track_2_equiv_len] = '\0'; success = true; - FURI_LOG_T( - TAG, - "found EMV_TAG_CARD_NUM %x (len=%d)", - EMV_TAG_CARD_NUM, - app->card_number_len); + FURI_LOG_T(TAG, "found EMV_TAG_TRACK_2_EQUIV %x : %s", tag, track_2_equiv); break; + } case EMV_TAG_PAN: memcpy(app->card_number, &buff[i], tlen); app->card_number_len = tlen; diff --git a/lib/nfc/protocols/emv.h b/lib/nfc/protocols/emv.h index 0ccf7c3e0..c5b089fdf 100644 --- a/lib/nfc/protocols/emv.h +++ b/lib/nfc/protocols/emv.h @@ -11,7 +11,8 @@ #define EMV_TAG_CARD_NAME 0x50 #define EMV_TAG_FCI 0xBF0C #define EMV_TAG_LOG_CTRL 0x9F4D -#define EMV_TAG_CARD_NUM 0x57 +#define EMV_TAG_TRACK_1_EQUIV 0x56 +#define EMV_TAG_TRACK_2_EQUIV 0x57 #define EMV_TAG_PAN 0x5A #define EMV_TAG_AFL 0x94 #define EMV_TAG_EXP_DATE 0x5F24 From eee5c3540060abb4c7e48dbdbbbc045f9cc1b1ed Mon Sep 17 00:00:00 2001 From: Giacomo Ferretti Date: Fri, 27 Jan 2023 06:51:47 +0100 Subject: [PATCH 24/26] NFC: add MIFARE MINI support (#2307) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * NFC: add MIFARE MINI support * Move new value to end of enum * nfc: added missing unit test Co-authored-by: gornekich Co-authored-by: あく --- applications/debug/unit_tests/nfc/nfc_test.c | 5 +++++ lib/nfc/helpers/nfc_generators.c | 22 ++++++++++++++++++++ lib/nfc/nfc_device.c | 18 ++++++++++++---- lib/nfc/nfc_types.c | 4 +++- lib/nfc/protocols/mifare_classic.c | 20 +++++++++++++----- lib/nfc/protocols/mifare_classic.h | 2 ++ 6 files changed, 61 insertions(+), 10 deletions(-) diff --git a/applications/debug/unit_tests/nfc/nfc_test.c b/applications/debug/unit_tests/nfc/nfc_test.c index e9e7b35f6..d613be2b9 100644 --- a/applications/debug/unit_tests/nfc/nfc_test.c +++ b/applications/debug/unit_tests/nfc/nfc_test.c @@ -466,6 +466,10 @@ static void mf_classic_generator_test(uint8_t uid_len, MfClassicType type) { nfc_device_free(nfc_keys); } +MU_TEST(mf_mini_file_test) { + mf_classic_generator_test(4, MfClassicTypeMini); +} + MU_TEST(mf_classic_1k_4b_file_test) { mf_classic_generator_test(4, MfClassicType1k); } @@ -486,6 +490,7 @@ MU_TEST_SUITE(nfc) { nfc_test_alloc(); MU_RUN_TEST(nfca_file_test); + MU_RUN_TEST(mf_mini_file_test); MU_RUN_TEST(mf_classic_1k_4b_file_test); MU_RUN_TEST(mf_classic_4k_4b_file_test); MU_RUN_TEST(mf_classic_1k_7b_file_test); diff --git a/lib/nfc/helpers/nfc_generators.c b/lib/nfc/helpers/nfc_generators.c index 769b9c7b6..590ff4d50 100644 --- a/lib/nfc/helpers/nfc_generators.c +++ b/lib/nfc/helpers/nfc_generators.c @@ -352,11 +352,27 @@ void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType } // Set SAK to 08 data->nfc_data.sak = 0x08; + } else if(type == MfClassicTypeMini) { + // Set every block to 0xFF + for(uint16_t i = 1; i < MF_MINI_TOTAL_SECTORS_NUM * 4; i += 1) { + if(mf_classic_is_sector_trailer(i)) { + nfc_generate_mf_classic_sector_trailer(mfc, i); + } else { + memset(&mfc->block[i].value, 0xFF, 16); + } + mf_classic_set_block_read(mfc, i, &mfc->block[i]); + } + // Set SAK to 09 + data->nfc_data.sak = 0x09; } mfc->type = type; } +static void nfc_generate_mf_mini(NfcDeviceData* data) { + nfc_generate_mf_classic(data, 4, MfClassicTypeMini); +} + static void nfc_generate_mf_classic_1k_4b_uid(NfcDeviceData* data) { nfc_generate_mf_classic(data, 4, MfClassicType1k); } @@ -438,6 +454,11 @@ static const NfcGenerator ntag_i2c_plus_2k_generator = { .generator_func = nfc_generate_ntag_i2c_plus_2k, }; +static const NfcGenerator mifare_mini_generator = { + .name = "Mifare Mini", + .generator_func = nfc_generate_mf_mini, +}; + static const NfcGenerator mifare_classic_1k_4b_uid_generator = { .name = "Mifare Classic 1k 4byte UID", .generator_func = nfc_generate_mf_classic_1k_4b_uid, @@ -472,6 +493,7 @@ const NfcGenerator* const nfc_generators[] = { &ntag_i2c_2k_generator, &ntag_i2c_plus_1k_generator, &ntag_i2c_plus_2k_generator, + &mifare_mini_generator, &mifare_classic_1k_4b_uid_generator, &mifare_classic_1k_7b_uid_generator, &mifare_classic_4k_4b_uid_generator, diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index d10eaa0e5..517913070 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -745,7 +745,10 @@ static bool nfc_device_save_mifare_classic_data(FlipperFormat* file, NfcDevice* do { if(!flipper_format_write_comment_cstr(file, "Mifare Classic specific data")) break; - if(data->type == MfClassicType1k) { + if(data->type == MfClassicTypeMini) { + if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "MINI")) break; + blocks = 20; + } else if(data->type == MfClassicType1k) { if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "1K")) break; blocks = 64; } else if(data->type == MfClassicType4k) { @@ -843,7 +846,10 @@ static bool nfc_device_load_mifare_classic_data(FlipperFormat* file, NfcDevice* do { // Read Mifare Classic type if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) break; - if(!furi_string_cmp(temp_str, "1K")) { + if(!furi_string_cmp(temp_str, "MINI")) { + data->type = MfClassicTypeMini; + data_blocks = 20; + } else if(!furi_string_cmp(temp_str, "1K")) { data->type = MfClassicType1k; data_blocks = 64; } else if(!furi_string_cmp(temp_str, "4K")) { @@ -918,7 +924,9 @@ static bool nfc_device_save_mifare_classic_keys(NfcDevice* dev) { if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break; if(!flipper_format_write_header_cstr(file, nfc_keys_file_header, nfc_keys_file_version)) break; - if(data->type == MfClassicType1k) { + if(data->type == MfClassicTypeMini) { + if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "MINI")) break; + } else if(data->type == MfClassicType1k) { if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "1K")) break; } else if(data->type == MfClassicType4k) { if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "4K")) break; @@ -968,7 +976,9 @@ bool nfc_device_load_key_cache(NfcDevice* dev) { if(furi_string_cmp_str(temp_str, nfc_keys_file_header)) break; if(version != nfc_keys_file_version) break; if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) break; - if(!furi_string_cmp(temp_str, "1K")) { + if(!furi_string_cmp(temp_str, "MINI")) { + data->type = MfClassicTypeMini; + } else if(!furi_string_cmp(temp_str, "1K")) { data->type = MfClassicType1k; } else if(!furi_string_cmp(temp_str, "4K")) { data->type = MfClassicType4k; diff --git a/lib/nfc/nfc_types.c b/lib/nfc/nfc_types.c index 427628769..02ca85580 100644 --- a/lib/nfc/nfc_types.c +++ b/lib/nfc/nfc_types.c @@ -55,7 +55,9 @@ const char* nfc_mf_ul_type(MfUltralightType type, bool full_name) { } const char* nfc_mf_classic_type(MfClassicType type) { - if(type == MfClassicType1k) { + if(type == MfClassicTypeMini) { + return "Mifare Mini 0.3K"; + } else if(type == MfClassicType1k) { return "Mifare Classic 1K"; } else if(type == MfClassicType4k) { return "Mifare Classic 4K"; diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index d1aadf06f..2f340a5ce 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -13,7 +13,9 @@ #define MF_CLASSIC_WRITE_BLOCK_CMD (0xA0) const char* mf_classic_get_type_str(MfClassicType type) { - if(type == MfClassicType1k) { + if(type == MfClassicTypeMini) { + return "MIFARE Mini 0.3K"; + } else if(type == MfClassicType1k) { return "MIFARE Classic 1K"; } else if(type == MfClassicType4k) { return "MIFARE Classic 4K"; @@ -73,7 +75,9 @@ MfClassicSectorTrailer* } uint8_t mf_classic_get_total_sectors_num(MfClassicType type) { - if(type == MfClassicType1k) { + if(type == MfClassicTypeMini) { + return MF_MINI_TOTAL_SECTORS_NUM; + } else if(type == MfClassicType1k) { return MF_CLASSIC_1K_TOTAL_SECTORS_NUM; } else if(type == MfClassicType4k) { return MF_CLASSIC_4K_TOTAL_SECTORS_NUM; @@ -83,7 +87,9 @@ uint8_t mf_classic_get_total_sectors_num(MfClassicType type) { } uint16_t mf_classic_get_total_block_num(MfClassicType type) { - if(type == MfClassicType1k) { + if(type == MfClassicTypeMini) { + return 20; + } else if(type == MfClassicType1k) { return 64; } else if(type == MfClassicType4k) { return 256; @@ -363,8 +369,12 @@ bool mf_classic_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { MfClassicType mf_classic_get_classic_type(int8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { UNUSED(ATQA1); - if((ATQA0 == 0x44 || ATQA0 == 0x04) && (SAK == 0x08 || SAK == 0x88 || SAK == 0x09)) { - return MfClassicType1k; + if((ATQA0 == 0x44 || ATQA0 == 0x04)) { + if((SAK == 0x08 || SAK == 0x88)) { + return MfClassicType1k; + } else if(SAK == 0x09) { + return MfClassicTypeMini; + } } else if((ATQA0 == 0x01) && (ATQA1 == 0x0F) && (SAK == 0x01)) { //skylanders support return MfClassicType1k; diff --git a/lib/nfc/protocols/mifare_classic.h b/lib/nfc/protocols/mifare_classic.h index 74beceb62..0346da0f7 100644 --- a/lib/nfc/protocols/mifare_classic.h +++ b/lib/nfc/protocols/mifare_classic.h @@ -6,6 +6,7 @@ #define MF_CLASSIC_BLOCK_SIZE (16) #define MF_CLASSIC_TOTAL_BLOCKS_MAX (256) +#define MF_MINI_TOTAL_SECTORS_NUM (5) #define MF_CLASSIC_1K_TOTAL_SECTORS_NUM (16) #define MF_CLASSIC_4K_TOTAL_SECTORS_NUM (40) @@ -20,6 +21,7 @@ typedef enum { MfClassicType1k, MfClassicType4k, + MfClassicTypeMini, } MfClassicType; typedef enum { From 126a9efd091ea949cb9a26a01b0ee7f8c22a4a68 Mon Sep 17 00:00:00 2001 From: Giacomo Ferretti Date: Fri, 27 Jan 2023 09:21:52 +0100 Subject: [PATCH 25/26] NFC: change from int8_t to uint8_t (#2302) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: gornekich Co-authored-by: あく --- firmware/targets/f7/api_symbols.csv | 2 +- lib/nfc/protocols/mifare_classic.c | 2 +- lib/nfc/protocols/mifare_classic.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 3d7bd7cd2..0e4af3c1d 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1880,7 +1880,7 @@ Function,-,mf_classic_dict_is_key_present,_Bool,"MfClassicDict*, uint8_t*" Function,-,mf_classic_dict_is_key_present_str,_Bool,"MfClassicDict*, FuriString*" Function,-,mf_classic_dict_rewind,_Bool,MfClassicDict* Function,-,mf_classic_emulator,_Bool,"MfClassicEmulator*, FuriHalNfcTxRxContext*" -Function,-,mf_classic_get_classic_type,MfClassicType,"int8_t, uint8_t, uint8_t" +Function,-,mf_classic_get_classic_type,MfClassicType,"uint8_t, uint8_t, uint8_t" Function,-,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*, uint8_t*" Function,-,mf_classic_get_sector_by_block,uint8_t,uint8_t Function,-,mf_classic_get_sector_trailer_block_num_by_sector,uint8_t,uint8_t diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index 2f340a5ce..5887ab4c1 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -367,7 +367,7 @@ bool mf_classic_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { } } -MfClassicType mf_classic_get_classic_type(int8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { +MfClassicType mf_classic_get_classic_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { UNUSED(ATQA1); if((ATQA0 == 0x44 || ATQA0 == 0x04)) { if((SAK == 0x08 || SAK == 0x88)) { diff --git a/lib/nfc/protocols/mifare_classic.h b/lib/nfc/protocols/mifare_classic.h index 0346da0f7..321ab5f03 100644 --- a/lib/nfc/protocols/mifare_classic.h +++ b/lib/nfc/protocols/mifare_classic.h @@ -96,7 +96,7 @@ const char* mf_classic_get_type_str(MfClassicType type); bool mf_classic_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK); -MfClassicType mf_classic_get_classic_type(int8_t ATQA0, uint8_t ATQA1, uint8_t SAK); +MfClassicType mf_classic_get_classic_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK); uint8_t mf_classic_get_total_sectors_num(MfClassicType type); From 24a23e5dc7b1719874f075abbf428bd5dd59e5e6 Mon Sep 17 00:00:00 2001 From: Emily Trau Date: Fri, 27 Jan 2023 20:41:55 +1100 Subject: [PATCH 26/26] debug apps: made runnable as .faps; sdk: resolved additional APIs in use by faps (#2333) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * sdk: resolve additional APIs in use by faps * debug tools: fixed battery_test, bt_debug, display_test, rpc_debug Co-authored-by: hedger Co-authored-by: hedger Co-authored-by: あく --- .../debug/battery_test_app/application.fam | 1 + .../battery_test_app/views/battery_info.c | 148 ++++++++++++++++++ .../battery_test_app/views/battery_info.h | 23 +++ .../debug/bt_debug_app/bt_debug_app.c | 7 +- .../debug/bt_debug_app/bt_debug_app.h | 5 +- .../debug/display_test/application.fam | 1 + .../debug/display_test/display_test.c | 1 - .../rpc_debug_app_scene_input_error_code.c | 6 +- applications/services/bt/bt_settings.h | 8 + firmware/targets/f7/api_symbols.csv | 8 +- lib/toolbox/SConscript | 1 + 11 files changed, 198 insertions(+), 11 deletions(-) create mode 100644 applications/debug/battery_test_app/views/battery_info.c create mode 100644 applications/debug/battery_test_app/views/battery_info.h diff --git a/applications/debug/battery_test_app/application.fam b/applications/debug/battery_test_app/application.fam index b388445cc..f97d10279 100644 --- a/applications/debug/battery_test_app/application.fam +++ b/applications/debug/battery_test_app/application.fam @@ -11,4 +11,5 @@ App( stack_size=1 * 1024, order=130, fap_category="Debug", + fap_libs=["assets"], ) diff --git a/applications/debug/battery_test_app/views/battery_info.c b/applications/debug/battery_test_app/views/battery_info.c new file mode 100644 index 000000000..5353a2e2a --- /dev/null +++ b/applications/debug/battery_test_app/views/battery_info.c @@ -0,0 +1,148 @@ +#include "battery_info.h" +#include +#include +#include + +#define LOW_CHARGE_THRESHOLD 10 +#define HIGH_DRAIN_CURRENT_THRESHOLD 100 + +struct BatteryInfo { + View* view; +}; + +static void draw_stat(Canvas* canvas, int x, int y, const Icon* icon, char* val) { + canvas_draw_frame(canvas, x - 7, y + 7, 30, 13); + canvas_draw_icon(canvas, x, y, icon); + canvas_set_color(canvas, ColorWhite); + canvas_draw_box(canvas, x - 4, y + 16, 24, 6); + canvas_set_color(canvas, ColorBlack); + canvas_draw_str_aligned(canvas, x + 8, y + 22, AlignCenter, AlignBottom, val); +}; + +static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { + char emote[20] = {}; + char header[20] = {}; + char value[20] = {}; + + int32_t drain_current = data->gauge_current * (-1000); + uint32_t charge_current = data->gauge_current * 1000; + + // Draw battery + canvas_draw_icon(canvas, x, y, &I_BatteryBody_52x28); + if(charge_current > 0) { + canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceCharging_29x14); + } else if(drain_current > HIGH_DRAIN_CURRENT_THRESHOLD) { + canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceConfused_29x14); + } else if(data->charge < LOW_CHARGE_THRESHOLD) { + canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNopower_29x14); + } else { + canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNormal_29x14); + } + + // Draw bubble + elements_bubble(canvas, 53, 0, 71, 39); + + // Set text + if(charge_current > 0) { + snprintf(emote, sizeof(emote), "%s", "Yummy!"); + snprintf(header, sizeof(header), "%s", "Charging at"); + snprintf( + value, + sizeof(value), + "%lu.%luV %lumA", + (uint32_t)(data->vbus_voltage), + (uint32_t)(data->vbus_voltage * 10) % 10, + charge_current); + } else if(drain_current > 0) { + snprintf( + emote, + sizeof(emote), + "%s", + drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "Oh no!" : "Om-nom-nom!"); + snprintf(header, sizeof(header), "%s", "Consumption is"); + snprintf( + value, + sizeof(value), + "%ld %s", + drain_current, + drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "mA!" : "mA"); + } else if(drain_current != 0) { + snprintf(header, 20, "..."); + } else if(data->charging_voltage < 4.2) { + // Non-default battery charging limit, mention it + snprintf(emote, sizeof(emote), "Charged!"); + snprintf(header, sizeof(header), "Limited to"); + snprintf( + value, + sizeof(value), + "%lu.%luV", + (uint32_t)(data->charging_voltage), + (uint32_t)(data->charging_voltage * 10) % 10); + } else { + snprintf(header, sizeof(header), "Charged!"); + } + + canvas_draw_str_aligned(canvas, 92, y + 3, AlignCenter, AlignCenter, emote); + canvas_draw_str_aligned(canvas, 92, y + 15, AlignCenter, AlignCenter, header); + canvas_draw_str_aligned(canvas, 92, y + 27, AlignCenter, AlignCenter, value); +}; + +static void battery_info_draw_callback(Canvas* canvas, void* context) { + furi_assert(context); + BatteryInfoModel* model = context; + + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + draw_battery(canvas, model, 0, 5); + + char batt_level[10]; + char temperature[10]; + char voltage[10]; + char health[10]; + + snprintf(batt_level, sizeof(batt_level), "%lu%%", (uint32_t)model->charge); + snprintf(temperature, sizeof(temperature), "%lu C", (uint32_t)model->gauge_temperature); + snprintf( + voltage, + sizeof(voltage), + "%lu.%01lu V", + (uint32_t)model->gauge_voltage, + (uint32_t)(model->gauge_voltage * 10) % 10UL); + snprintf(health, sizeof(health), "%d%%", model->health); + + draw_stat(canvas, 8, 42, &I_Battery_16x16, batt_level); + draw_stat(canvas, 40, 42, &I_Temperature_16x16, temperature); + draw_stat(canvas, 72, 42, &I_Voltage_16x16, voltage); + draw_stat(canvas, 104, 42, &I_Health_16x16, health); +} + +BatteryInfo* battery_info_alloc() { + BatteryInfo* battery_info = malloc(sizeof(BatteryInfo)); + battery_info->view = view_alloc(); + view_set_context(battery_info->view, battery_info); + view_allocate_model(battery_info->view, ViewModelTypeLocking, sizeof(BatteryInfoModel)); + view_set_draw_callback(battery_info->view, battery_info_draw_callback); + + return battery_info; +} + +void battery_info_free(BatteryInfo* battery_info) { + furi_assert(battery_info); + view_free(battery_info->view); + free(battery_info); +} + +View* battery_info_get_view(BatteryInfo* battery_info) { + furi_assert(battery_info); + return battery_info->view; +} + +void battery_info_set_data(BatteryInfo* battery_info, BatteryInfoModel* data) { + furi_assert(battery_info); + furi_assert(data); + with_view_model( + battery_info->view, + BatteryInfoModel * model, + { memcpy(model, data, sizeof(BatteryInfoModel)); }, + true); +} diff --git a/applications/debug/battery_test_app/views/battery_info.h b/applications/debug/battery_test_app/views/battery_info.h new file mode 100644 index 000000000..7bfacf69e --- /dev/null +++ b/applications/debug/battery_test_app/views/battery_info.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +typedef struct BatteryInfo BatteryInfo; + +typedef struct { + float vbus_voltage; + float gauge_voltage; + float gauge_current; + float gauge_temperature; + float charging_voltage; + uint8_t charge; + uint8_t health; +} BatteryInfoModel; + +BatteryInfo* battery_info_alloc(); + +void battery_info_free(BatteryInfo* battery_info); + +View* battery_info_get_view(BatteryInfo* battery_info); + +void battery_info_set_data(BatteryInfo* battery_info, BatteryInfoModel* data); diff --git a/applications/debug/bt_debug_app/bt_debug_app.c b/applications/debug/bt_debug_app/bt_debug_app.c index 405051a4a..bf13f6570 100644 --- a/applications/debug/bt_debug_app/bt_debug_app.c +++ b/applications/debug/bt_debug_app/bt_debug_app.c @@ -31,9 +31,6 @@ uint32_t bt_debug_start_view(void* context) { BtDebugApp* bt_debug_app_alloc() { BtDebugApp* app = malloc(sizeof(BtDebugApp)); - // Load settings - bt_settings_load(&app->settings); - // Gui app->gui = furi_record_open(RECORD_GUI); @@ -105,13 +102,15 @@ int32_t bt_debug_app(void* p) { } BtDebugApp* app = bt_debug_app_alloc(); + // Was bt active? + const bool was_active = furi_hal_bt_is_active(); // Stop advertising furi_hal_bt_stop_advertising(); view_dispatcher_run(app->view_dispatcher); // Restart advertising - if(app->settings.enabled) { + if(was_active) { furi_hal_bt_start_advertising(); } bt_debug_app_free(app); diff --git a/applications/debug/bt_debug_app/bt_debug_app.h b/applications/debug/bt_debug_app/bt_debug_app.h index cd59e4d00..0ad94d7dd 100644 --- a/applications/debug/bt_debug_app/bt_debug_app.h +++ b/applications/debug/bt_debug_app/bt_debug_app.h @@ -4,15 +4,14 @@ #include #include #include +#include + #include -#include #include "views/bt_carrier_test.h" #include "views/bt_packet_test.h" -#include typedef struct { - BtSettings settings; Gui* gui; ViewDispatcher* view_dispatcher; Submenu* submenu; diff --git a/applications/debug/display_test/application.fam b/applications/debug/display_test/application.fam index 4b40322fb..e8a00d2ae 100644 --- a/applications/debug/display_test/application.fam +++ b/applications/debug/display_test/application.fam @@ -5,6 +5,7 @@ App( entry_point="display_test_app", cdefines=["APP_DISPLAY_TEST"], requires=["gui"], + fap_libs=["misc"], stack_size=1 * 1024, order=120, fap_category="Debug", diff --git a/applications/debug/display_test/display_test.c b/applications/debug/display_test/display_test.c index 5b46d2b41..8065a23a1 100644 --- a/applications/debug/display_test/display_test.c +++ b/applications/debug/display_test/display_test.c @@ -91,7 +91,6 @@ static void display_test_reload_config(DisplayTest* instance) { instance->config_contrast, instance->config_regulation_ratio, instance->config_bias); - gui_update(instance->gui); } static void display_config_set_bias(VariableItem* item) { diff --git a/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_input_error_code.c b/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_input_error_code.c index eae12e6ee..367ca7a4f 100644 --- a/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_input_error_code.c +++ b/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_input_error_code.c @@ -44,7 +44,11 @@ bool rpc_debug_app_scene_input_error_code_on_event(void* context, SceneManagerEv if(event.type == SceneManagerEventTypeCustom) { if(event.event == RpcDebugAppCustomEventInputErrorCode) { - rpc_system_app_set_error_code(app->rpc, (uint32_t)atol(app->text_store)); + char* end; + int error_code = strtol(app->text_store, &end, 10); + if(!*end) { + rpc_system_app_set_error_code(app->rpc, error_code); + } scene_manager_previous_scene(app->scene_manager); consumed = true; } diff --git a/applications/services/bt/bt_settings.h b/applications/services/bt/bt_settings.h index 260d9c0e0..9ed8be89c 100644 --- a/applications/services/bt/bt_settings.h +++ b/applications/services/bt/bt_settings.h @@ -5,6 +5,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { bool enabled; } BtSettings; @@ -12,3 +16,7 @@ typedef struct { bool bt_settings_load(BtSettings* bt_settings); bool bt_settings_save(BtSettings* bt_settings); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 0e4af3c1d..0e027a6a2 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,11.7,, +Version,+,11.8,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -188,6 +188,7 @@ Header,+,lib/toolbox/stream/file_stream.h,, Header,+,lib/toolbox/stream/stream.h,, Header,+,lib/toolbox/stream/string_stream.h,, Header,+,lib/toolbox/tar/tar_archive.h,, +Header,+,lib/toolbox/value_index.h,, Header,+,lib/toolbox/version.h,, Function,-,LL_ADC_CommonDeInit,ErrorStatus,ADC_Common_TypeDef* Function,-,LL_ADC_CommonInit,ErrorStatus,"ADC_Common_TypeDef*, LL_ADC_CommonInitTypeDef*" @@ -2066,7 +2067,7 @@ Function,-,posix_memalign,int,"void**, size_t, size_t" Function,-,pow,double,"double, double" Function,-,pow10,double,double Function,-,pow10f,float,float -Function,-,power_enable_low_battery_level_notification,void,"Power*, _Bool" +Function,+,power_enable_low_battery_level_notification,void,"Power*, _Bool" Function,+,power_get_info,void,"Power*, PowerInfo*" Function,+,power_get_pubsub,FuriPubSub*,Power* Function,+,power_is_battery_healthy,_Bool,Power* @@ -2804,6 +2805,9 @@ Function,-,vTimerSetTimerNumber,void,"TimerHandle_t, UBaseType_t" Function,+,validator_is_file_alloc_init,ValidatorIsFile*,"const char*, const char*, const char*" Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*" Function,+,validator_is_file_free,void,ValidatorIsFile* +Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t" +Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t" +Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t" Function,+,variable_item_get_context,void*,VariableItem* Function,+,variable_item_get_current_value_index,uint8_t,VariableItem* Function,+,variable_item_list_add,VariableItem*,"VariableItemList*, const char*, uint8_t, VariableItemChangeCallback, void*" diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index 724d25afa..8ce45d25f 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -20,6 +20,7 @@ env.Append( File("saved_struct.h"), File("version.h"), File("float_tools.h"), + File("value_index.h"), File("tar/tar_archive.h"), File("stream/stream.h"), File("stream/file_stream.h"),